Skip to content

Fix SVE benchmark CreateWhileLessThanMask API rename for .NET 11#5183

Merged
LoopedBard3 merged 5 commits intodotnet:mainfrom
LoopedBard3:FixSVETests
Apr 2, 2026
Merged

Fix SVE benchmark CreateWhileLessThanMask API rename for .NET 11#5183
LoopedBard3 merged 5 commits intodotnet:mainfrom
LoopedBard3:FixSVETests

Conversation

@LoopedBard3
Copy link
Copy Markdown
Member

@LoopedBard3 LoopedBard3 commented Mar 30, 2026

Fix SVE benchmark compatibility with CreateWhileLessThanMask API rename

Problem

The .NET runtime renamed the Sve.CreateWhileLessThanMask methods from bit-width suffixes to type-name suffixes:

  • CreateWhileLessThanMask8BitCreateWhileLessThanMaskByte
  • CreateWhileLessThanMask16BitCreateWhileLessThanMaskUInt16
  • CreateWhileLessThanMask32BitCreateWhileLessThanMaskUInt32
  • CreateWhileLessThanMask64BitCreateWhileLessThanMaskUInt64
  • New type-specific variants added: CreateWhileLessThanMaskInt16, CreateWhileLessThanMaskInt32, CreateWhileLessThanMaskSingle

The 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 MissingMethodException at runtime for all SVE benchmarks.

Solution

Introduced SveMaskHelper, a compatibility shim that all 22 SVE benchmark files call instead of Sve.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.

  • Direct-bind cases (Byte, UInt16, UInt32, UInt64): old and new names share the same return type, so Delegate.CreateDelegate binds directly to whichever method is found.
  • Cast-wrapping cases (Int16, Int32, Single): the old API returned an unsigned vector (e.g. Vector<uint>), but the caller needs a signed/float reinterpret. A thin lambda wraps the old delegate and uses Unsafe.As to reinterpret the bits.

Performance impact

CreateWhileLessThanMask is 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

  • New: src/benchmarks/micro/sve/SveMaskHelper.cs — reflection + delegate caching shim
  • Modified: 22 SVE benchmark files — replaced direct Sve.CreateWhileLessThanMask*Bit() calls with SveMaskHelper.CreateWhileLessThanMask*() calls

Seems to have been updated as part of dotnet/runtime#124081.

Test run: https://dev.azure.com/dnceng/internal/_build/results?buildId=2940679&view=results

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 SveMaskHelper shim with #if NET11_0_OR_GREATER to map old bit-width-suffixed APIs to new type-suffixed APIs.
  • Replace direct Sve.CreateWhileLessThanMask{8,16,32,64}Bit usages across SVE benchmarks with SveMaskHelper calls.
  • 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>
@LoopedBard3 LoopedBard3 marked this pull request as ready for review April 1, 2026 17:58
@LoopedBard3
Copy link
Copy Markdown
Member Author

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.

@LoopedBard3 LoopedBard3 merged commit 619a125 into dotnet:main Apr 2, 2026
71 of 74 checks passed
@LoopedBard3 LoopedBard3 deleted the FixSVETests branch April 2, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants