Fix SVE benchmark CreateWhileLessThanMask API rename for .NET 11#5183
Fix SVE benchmark CreateWhileLessThanMask API rename for .NET 11#5183LoopedBard3 merged 5 commits intodotnet:mainfrom
Conversation
The .NET 11 runtime renamed CreateWhileLessThanMask methods from bit-width suffixes (8Bit, 16Bit, 32Bit, 64Bit) to type-name suffixes (Byte, UInt16, Int32, UInt32, Single, UInt64, etc.). This caused MissingMethodException at runtime on SVE-capable machines: - CreateWhileLessThanMask8Bit -> CreateWhileLessThanMaskByte - CreateWhileLessThanMask16Bit -> CreateWhileLessThanMaskUInt16/Int16 - CreateWhileLessThanMask32Bit -> CreateWhileLessThanMaskUInt32/Int32/Single - CreateWhileLessThanMask64Bit -> CreateWhileLessThanMaskUInt64 Added SveMaskHelper shim class with #if NET11_0_OR_GREATER conditionals to support both the old API (net9.0/net10.0) and new API (net11.0+). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates SVE microbenchmarks to handle the .NET 11 Sve.CreateWhileLessThanMask* API rename by routing predicate creation through a compatibility shim, avoiding runtime MissingMethodException on SVE-capable machines.
Changes:
- Introduce
SveMaskHelpershim with#if NET11_0_OR_GREATERto map old bit-width-suffixed APIs to new type-suffixed APIs. - Replace direct
Sve.CreateWhileLessThanMask{8,16,32,64}Bitusages across SVE benchmarks withSveMaskHelpercalls. - Remove many now-unnecessary casts at call sites by centralizing the compatibility logic in the helper.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/benchmarks/micro/sve/VectorMax.cs | Switch 16-bit loop predicate creation to SveMaskHelper for .NET 11 compatibility. |
| src/benchmarks/micro/sve/UpscaleFilter.cs | Switch 8-bit loop predicate creation to SveMaskHelper. |
| src/benchmarks/micro/sve/TCPChecksum.cs | Switch 16-bit loop predicate creation to SveMaskHelper (UInt16). |
| src/benchmarks/micro/sve/SveMaskHelper.cs | Add shim methods that select old vs new CreateWhileLessThanMask* APIs via preprocessor. |
| src/benchmarks/micro/sve/StrLen.cs | Switch 8-bit loop predicate creation to SveMaskHelper. |
| src/benchmarks/micro/sve/StrIndexOf.cs | Switch 16-bit loop predicate creation to SveMaskHelper (UInt16). |
| src/benchmarks/micro/sve/StrCmp.cs | Switch 8-bit loop predicate creation to SveMaskHelper. |
| src/benchmarks/micro/sve/SquareRoot.cs | Switch 32-bit loop predicate creation to SveMaskHelper (UInt32). |
| src/benchmarks/micro/sve/SobelFilter.cs | Switch 32-bit loop predicate creation to SveMaskHelper (Single) for float loads. |
| src/benchmarks/micro/sve/ScatterStore.cs | Switch 32-bit loop predicate creation to SveMaskHelper (UInt32). |
| src/benchmarks/micro/sve/Partition.cs | Switch 32-bit loop predicate creation to SveMaskHelper, including long counter overload path. |
| src/benchmarks/micro/sve/PairwiseAdd.cs | Switch 32-bit loop predicate creation to SveMaskHelper (Int32). |
| src/benchmarks/micro/sve/OddEvenSort.cs | Switch 32-bit loop predicate creation to SveMaskHelper (UInt32). |
| src/benchmarks/micro/sve/MultiplyPow2.cs | Switch 64-bit loop predicate creation to SveMaskHelper (UInt64). |
| src/benchmarks/micro/sve/MultiplyAdd.cs | Switch 32-bit loop predicate creation to SveMaskHelper (Int32). |
| src/benchmarks/micro/sve/Logarithm.cs | Switch 32-bit loop predicate creation to SveMaskHelper (UInt32). |
| src/benchmarks/micro/sve/GatherLoad.cs | Switch 32-bit loop predicate creation to SveMaskHelper (UInt32). |
| src/benchmarks/micro/sve/FP64Overflow.cs | Switch 64-bit loop predicate creation to SveMaskHelper (UInt64). |
| src/benchmarks/micro/sve/FastDivision.cs | Switch 64-bit loop predicate creation to SveMaskHelper (UInt64). |
| src/benchmarks/micro/sve/Exponent.cs | Switch 32-bit loop predicate creation to SveMaskHelper (UInt32). |
| src/benchmarks/micro/sve/ComplexMultiply.cs | Switch 32/64-bit loop predicate creation to SveMaskHelper (UInt32/UInt64). |
| src/benchmarks/micro/sve/ComplexDotProduct.cs | Switch 32-bit loop predicate creation to SveMaskHelper (Int32). |
| src/benchmarks/micro/sve/Clamp.cs | Switch 32-bit loop predicate creation to SveMaskHelper (Int32). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ompat The SDK ref assemblies have old method names (CreateWhileLessThanMask8Bit etc.) while the runtime corerun has new names (CreateWhileLessThanMaskByte etc.). Compile-time conditionals cannot work since both builds define NET11_0_OR_GREATER. Use reflection at startup to detect which names exist, cache as delegates. Cast-wrapping lambdas handle cases where old API returns unsigned type but caller needs signed/float reinterpret (e.g. Vector<uint> -> Vector<int>). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit 048882b.
|
Test run was successful and this seems like a workable approach for these tests. Eventually we can split them into and old and new version (net11/net10), but this should keep it working until everything is flowed everywhere properly. When we change this test, it will cause changes in results, but we only have one config running these at the moment. |
Fix SVE benchmark compatibility with CreateWhileLessThanMask API rename
Problem
The .NET runtime renamed the
Sve.CreateWhileLessThanMaskmethods from bit-width suffixes to type-name suffixes:CreateWhileLessThanMask8Bit→CreateWhileLessThanMaskByteCreateWhileLessThanMask16Bit→CreateWhileLessThanMaskUInt16CreateWhileLessThanMask32Bit→CreateWhileLessThanMaskUInt32CreateWhileLessThanMask64Bit→CreateWhileLessThanMaskUInt64CreateWhileLessThanMaskInt16,CreateWhileLessThanMaskInt32,CreateWhileLessThanMaskSingleThe perf CI compiles benchmarks with the SDK (which still has old names in its ref assemblies) but runs them with a corerun built from runtime main (which only has new names). This causes
MissingMethodExceptionat runtime for all SVE benchmarks.Solution
Introduced
SveMaskHelper, a compatibility shim that all 22 SVE benchmark files call instead ofSve.CreateWhileLessThanMask*directly. At startup, it uses reflection to detect which method names exist on the runtime, caches the result as delegates, and dispatches through those.Delegate.CreateDelegatebinds directly to whichever method is found.Vector<uint>), but the caller needs a signed/float reinterpret. A thin lambda wraps the old delegate and usesUnsafe.Asto reinterpret the bits.Performance impact
CreateWhileLessThanMaskis loop predication plumbing, not the core workload being measured. The delegate indirection adds minor overhead (~2-5ns per call) but does not affect the JIT intrinsification of the actual SVE operations under test (Add, Multiply, LoadVector, CompareEqual, etc.). Once the SDK ships with the new names, this shim can be replaced with direct calls.Changes
src/benchmarks/micro/sve/SveMaskHelper.cs— reflection + delegate caching shimSve.CreateWhileLessThanMask*Bit()calls withSveMaskHelper.CreateWhileLessThanMask*()callsSeems to have been updated as part of dotnet/runtime#124081.
Test run: https://dev.azure.com/dnceng/internal/_build/results?buildId=2940679&view=results