-
Notifications
You must be signed in to change notification settings - Fork 6k
Description
Description
Arm64 SVE has a number of nonfaulting load APIs, eg LoadVectorByteNonFaultingZeroExtendToInt16()
.
All of them have been updated to include a mask
argument as the first position.
API review is here: dotnet/runtime#108234
Note SVE is currently in preview mode.
Version
10.0
Previous behavior
All NonFaulting loads would load a full vector.
To do a NonFaulting load with masked out elements a user would do Sve.ConditionalSelect(mask, Sve.LoadVector*NonFaulting*(addr), zero);
New behavior
All NonFaulting loads are masked.
To do a NonFaulting load for all element, a user would do Sve.LoadVector*NonFaulting*(Sve.CreateTrueMask*(), addr);
Type of breaking change
- Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
- Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
- Behavioral change: Existing binaries might behave differently at run time.
Reason for change
This is because a non-faulting load will update the FFR register depending on what vector lanes are loaded. Therefore we can't do that standard conversion of ConditionalSelect(mask, LoadVectorNonFaulting(addr), zero);
to a masked load. Therefore the only valid way of implementing a masked nonfaulting load is by exposing it as an API.
Recommended action
Any existing uses of Sve.ConditionalSelect(mask, Sve.LoadVector*NonFaulting*(addr), zero);
can be simplified to Sve.LoadVector*NonFaulting*(mask, addr);
Any other uses of non faulting loads should updated to include a true mask, eg: Sve.LoadVectorNonFaulting(Sve.CreateTrueMask*(), addr);`
Feature area
Intrinsics
Affected APIs
In .NET9:
public partial class Sve
{
public static unsafe Vector<short> LoadVectorByteNonFaultingZeroExtendToInt16(byte* address); // LDNF1B
public static unsafe Vector<int> LoadVectorByteNonFaultingZeroExtendToInt32(byte* address); // LDNF1B
public static unsafe Vector<long> LoadVectorByteNonFaultingZeroExtendToInt64(byte* address); // LDNF1B
public static unsafe Vector<ushort> LoadVectorByteNonFaultingZeroExtendToUInt16(byte* address); // LDNF1B
public static unsafe Vector<uint> LoadVectorByteNonFaultingZeroExtendToUInt32(byte* address); // LDNF1B
public static unsafe Vector<ulong> LoadVectorByteNonFaultingZeroExtendToUInt64(byte* address); // LDNF1B
public static unsafe Vector<int> LoadVectorInt16NonFaultingSignExtendToInt32(short* address); // LDNF1SH
public static unsafe Vector<long> LoadVectorInt16NonFaultingSignExtendToInt64(short* address); // LDNF1SH
public static unsafe Vector<uint> LoadVectorInt16NonFaultingSignExtendToUInt32(short* address); // LDNF1SH
public static unsafe Vector<ulong> LoadVectorInt16NonFaultingSignExtendToUInt64(short* address); // LDNF1SH
public static unsafe Vector<long> LoadVectorInt32NonFaultingSignExtendToInt64(int* address); // LDNF1SW
public static unsafe Vector<ulong> LoadVectorInt32NonFaultingSignExtendToUInt64(int* address); // LDNF1SW
/// T: float, double, sbyte, short, int, long, byte, ushort, uint, ulong
public static unsafe Vector<T> LoadVectorNonFaulting(T* address); // LDNF1W or LDNF1D or LDNF1B or LDNF1H
public static unsafe Vector<short> LoadVectorSByteNonFaultingSignExtendToInt16(sbyte* address); // LDNF1SB
public static unsafe Vector<int> LoadVectorSByteNonFaultingSignExtendToInt32(sbyte* address); // LDNF1SB
public static unsafe Vector<long> LoadVectorSByteNonFaultingSignExtendToInt64(sbyte* address); // LDNF1SB
public static unsafe Vector<ushort> LoadVectorSByteNonFaultingSignExtendToUInt16(sbyte* address); // LDNF1SB
public static unsafe Vector<uint> LoadVectorSByteNonFaultingSignExtendToUInt32(sbyte* address); // LDNF1SB
public static unsafe Vector<ulong> LoadVectorSByteNonFaultingSignExtendToUInt64(sbyte* address); // LDNF1SB
public static unsafe Vector<int> LoadVectorUInt16NonFaultingZeroExtendToInt32(ushort* address); // LDNF1H
public static unsafe Vector<long> LoadVectorUInt16NonFaultingZeroExtendToInt64(ushort* address); // LDNF1H
public static unsafe Vector<uint> LoadVectorUInt16NonFaultingZeroExtendToUInt32(ushort* address); // LDNF1H
public static unsafe Vector<ulong> LoadVectorUInt16NonFaultingZeroExtendToUInt64(ushort* address); // LDNF1H
public static unsafe Vector<long> LoadVectorUInt32NonFaultingZeroExtendToInt64(uint* address); // LDNF1W
public static unsafe Vector<ulong> LoadVectorUInt32NonFaultingZeroExtendToUInt64(uint* address); // LDNF1W
}
In .NET10:
public partial class Sve
{
public static unsafe Vector<short> LoadVectorByteNonFaultingZeroExtendToInt16(Vector<short> mask, byte* address); // LDNF1B
public static unsafe Vector<int> LoadVectorByteNonFaultingZeroExtendToInt32(Vector<int> mask, byte* address); // LDNF1B
public static unsafe Vector<long> LoadVectorByteNonFaultingZeroExtendToInt64(Vector<long> mask, byte* address); // LDNF1B
public static unsafe Vector<ushort> LoadVectorByteNonFaultingZeroExtendToUInt16(Vector<ushort> mask, byte* address); // LDNF1B
public static unsafe Vector<uint> LoadVectorByteNonFaultingZeroExtendToUInt32(Vector<uint> mask, byte* address); // LDNF1B
public static unsafe Vector<ulong> LoadVectorByteNonFaultingZeroExtendToUInt64(Vector<ulong> mask, byte* address); // LDNF1B
public static unsafe Vector<int> LoadVectorInt16NonFaultingSignExtendToInt32(Vector<int> mask, short* address); // LDNF1SH
public static unsafe Vector<long> LoadVectorInt16NonFaultingSignExtendToInt64(Vector<long> mask, short* address); // LDNF1SH
public static unsafe Vector<uint> LoadVectorInt16NonFaultingSignExtendToUInt32(Vector<uint> mask, short* address); // LDNF1SH
public static unsafe Vector<ulong> LoadVectorInt16NonFaultingSignExtendToUInt64(Vector<ulong> mask, short* address); // LDNF1SH
public static unsafe Vector<long> LoadVectorInt32NonFaultingSignExtendToInt64(Vector<long> mask, int* address); // LDNF1SW
public static unsafe Vector<ulong> LoadVectorInt32NonFaultingSignExtendToUInt64(Vector<ulong> mask, int* address); // LDNF1SW
/// T: float, double, sbyte, short, int, long, byte, ushort, uint, ulong
public static unsafe Vector<T> LoadVectorNonFaulting(Vector<T> mask, T* address); // LDNF1W or LDNF1D or LDNF1B or LDNF1H
public static unsafe Vector<short> LoadVectorSByteNonFaultingSignExtendToInt16(Vector<short> mask, sbyte* address); // LDNF1SB
public static unsafe Vector<int> LoadVectorSByteNonFaultingSignExtendToInt32(Vector<int> mask, sbyte* address); // LDNF1SB
public static unsafe Vector<long> LoadVectorSByteNonFaultingSignExtendToInt64(Vector<long> mask, sbyte* address); // LDNF1SB
public static unsafe Vector<ushort> LoadVectorSByteNonFaultingSignExtendToUInt16(Vector<ushort> mask, sbyte* address); // LDNF1SB
public static unsafe Vector<uint> LoadVectorSByteNonFaultingSignExtendToUInt32(Vector<uint> mask, sbyte* address); // LDNF1SB
public static unsafe Vector<ulong> LoadVectorSByteNonFaultingSignExtendToUInt64(Vector<ulong> mask, sbyte* address); // LDNF1SB
public static unsafe Vector<int> LoadVectorUInt16NonFaultingZeroExtendToInt32(Vector<int> mask, ushort* address); // LDNF1H
public static unsafe Vector<long> LoadVectorUInt16NonFaultingZeroExtendToInt64(Vector<long> mask, ushort* address); // LDNF1H
public static unsafe Vector<uint> LoadVectorUInt16NonFaultingZeroExtendToUInt32(Vector<uint> mask, ushort* address); // LDNF1H
public static unsafe Vector<ulong> LoadVectorUInt16NonFaultingZeroExtendToUInt64(Vector<ulong> mask, ushort* address); // LDNF1H
public static unsafe Vector<long> LoadVectorUInt32NonFaultingZeroExtendToInt64(Vector<long> mask, uint* address); // LDNF1W
public static unsafe Vector<ulong> LoadVectorUInt32NonFaultingZeroExtendToUInt64(Vector<ulong> mask, uint* address); // LDNF1W
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Status