Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
All Arm64 SVE nonfaulting load APIs have been updated to include a mask
parameter in the first position. This change affects all methods with LoadVector*NonFaulting
in their name in the System.Runtime.Intrinsics.Arm.Sve class.
Version introduced
.NET 10 Preview 7
Previous behavior
Previously, nonfaulting load APIs took only an address parameter and loaded a full vector:
Vector<short> result = Sve.LoadVectorByteNonFaultingZeroExtendToInt16(address);
To do nonfaulting load with masked-out elements, you had to use ConditionalSelect:
Vector<short> maskedResult = Sve.ConditionalSelect(
mask,
Sve.LoadVectorByteNonFaultingZeroExtendToInt16(address),
zero);
New behavior
Starting in .NET 10, nonfaulting load APIs require a mask parameter as the first argument.
To do a nonfaulting load for all elements, create and pass a true mask: Sve.LoadVector*NonFaulting*(Sve.CreateTrueMask*(), addr);
Type of breaking change
This change can affect binary compatibility and source compatibility.
Reason for change
This change was necessary because a nonfaulting load updates the first fault register (FFR) depending on which vector lanes are loaded. The standard conversion of ConditionalSelect(mask, LoadVectorNonFaulting(addr), zero)
to a masked load can't be used because it doesn't properly handle the FFR register state. Therefore, the only valid way to implement a masked nonfaulting load is by exposing it as a dedicated API.
Recommended action
- For existing uses of
Sve.ConditionalSelect(mask, Sve.LoadVector*NonFaulting*(addr), zero)
, replace them withSve.LoadVector*NonFaulting*(mask, addr)
. - Update other uses of nonfaulting loads to include a true mask:
Sve.LoadVector*NonFaulting*(Sve.CreateTrueMask*(), addr)
.
Affected APIs
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToInt16(Byte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToInt32(Byte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToInt64(Byte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToUInt16(Byte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToUInt32(Byte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToUInt64(Byte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToInt32(Int16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToInt64(Int16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToUInt32(Int16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToUInt64(Int16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt32NonFaultingSignExtendToInt64(Int32*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt32NonFaultingSignExtendToUInt64(Int32*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToInt16(SByte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToInt32(SByte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToInt64(SByte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToUInt16(SByte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToUInt32(SByte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToUInt64(SByte*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToInt32(UInt16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToInt64(UInt16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToUInt32(UInt16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToUInt64(UInt16*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt32NonFaultingZeroExtendToInt64(UInt32*)
- System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt32NonFaultingZeroExtendToUInt64(UInt32*)