Skip to content

Add SVE2 API skeleton and implement BitwiseClearXor #115428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/jit/hwintrinsic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ static const HWIntrinsicIsaRange hwintrinsicIsaRangeArray[] = {
{ NI_Illegal, NI_Illegal }, // VectorT128
{ NI_Illegal, NI_Illegal }, // Rcpc2
{ FIRST_NI_Sve, LAST_NI_Sve },
{ NI_Illegal, NI_Illegal }, // Sve2
{ FIRST_NI_Sve2, LAST_NI_Sve2 }, // Sve2
{ FIRST_NI_ArmBase_Arm64, LAST_NI_ArmBase_Arm64 },
{ FIRST_NI_AdvSimd_Arm64, LAST_NI_AdvSimd_Arm64 },
{ NI_Illegal, NI_Illegal }, // Aes_Arm64
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/jit/hwintrinsiccodegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2649,6 +2649,16 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
break;
}

case NI_Sve2_BitwiseClearXor:
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
GetEmitter()->emitInsSve_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, op1Reg);
}
// Always use the lane size D. It's a bitwise operation so this is fine for all integer vector types.
GetEmitter()->emitInsSve_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, INS_OPTS_SCALABLE_D);
break;

default:
unreached();
}
Expand Down
11 changes: 9 additions & 2 deletions src/coreclr/jit/hwintrinsiclistarm64sve.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,16 @@ HARDWARE_INTRINSIC(Sve, ZipLow,
// 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}
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// Special intrinsics that are generated during importing or lowering
// SVE2 Intrinsics
#define FIRST_NI_Sve2 NI_Sve2_BitwiseClearXor
HARDWARE_INTRINSIC(Sve2, BitwiseClearXor, -1, 3, {INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics)
#define LAST_NI_Sve2 NI_Sve2_BitwiseClearXor

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// 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}
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// Special intrinsics that are generated during importing or lowering
#define SPECIAL_NI_Sve NI_Sve_ConditionalExtractAfterLastActiveElementScalar
HARDWARE_INTRINSIC(Sve, ConditionalExtractAfterLastActiveElementScalar, 0, 3, {INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta, INS_sve_clasta}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_HasRMWSemantics|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, ConditionalExtractLastActiveElementScalar, 0, 3, {INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb, INS_sve_clastb}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_HasRMWSemantics|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation)
Expand All @@ -326,7 +334,6 @@ HARDWARE_INTRINSIC(Sve, StoreAndZipx2,
HARDWARE_INTRINSIC(Sve, StoreAndZipx3, -1, 3, {INS_sve_st3b, INS_sve_st3b, INS_sve_st3h, INS_sve_st3h, INS_sve_st3w, INS_sve_st3w, INS_sve_st3d, INS_sve_st3d, INS_sve_st3w, INS_sve_st3d}, HW_Category_MemoryStore, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_NeedsConsecutiveRegisters)
HARDWARE_INTRINSIC(Sve, StoreAndZipx4, -1, 3, {INS_sve_st4b, INS_sve_st4b, INS_sve_st4h, INS_sve_st4h, INS_sve_st4w, INS_sve_st4w, INS_sve_st4d, INS_sve_st4d, INS_sve_st4w, INS_sve_st4d}, HW_Category_MemoryStore, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_NeedsConsecutiveRegisters)


#endif // FEATURE_HW_INTRINSIC

#undef HARDWARE_INTRINSIC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,11 @@
<type fullname="System.Runtime.Intrinsics.Arm.Sve/Arm64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.Arm.Sve2">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.Arm.Sve2/Arm64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
</assembly>
</linker>
Original file line number Diff line number Diff line change
Expand Up @@ -2712,6 +2712,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sha1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sha256.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sve.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sve2.cs" />
</ItemGroup>
<ItemGroup Condition="'$(SupportsArmIntrinsics)' != 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\AdvSimd.PlatformNotSupported.cs" />
Expand All @@ -2723,6 +2724,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sha1.PlatformNotSupported.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sha256.PlatformNotSupported.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sve.PlatformNotSupported.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Arm\Sve2.PlatformNotSupported.cs" />
</ItemGroup>
<ItemGroup Condition="'$(SupportsWasmIntrinsics)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Wasm\WasmBase.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Numerics;

namespace System.Runtime.Intrinsics.Arm
{
/// <summary>
/// This class provides access to the ARM SVE hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
[Experimental(Experimentals.ArmSveDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public abstract class Sve2 : Sve
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just need to confirm that this inheritance matches the agreed design, as there was some discrepancy in our code generation scripts? I assumed it should be like this, as the architecture has this dependency and some of the API design issues had this inheritance.

Copy link
Member

Choose a reason for hiding this comment

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

This makes sense to me.

{
internal Sve2() { }

public static new bool IsSupported { get => IsSupported; }

[Intrinsic]
public new abstract class Arm64 : Sve.Arm64
{
internal Arm64() { }

public static new bool IsSupported { get => IsSupported; }
}

// Bitwise clear and exclusive OR

/// <summary>
/// svuint8_t svbcax[_u8](svuint8_t op1, svuint8_t op2, svuint8_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<byte> BitwiseClearXor(Vector<byte> xor, Vector<byte> value, Vector<byte> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svint16_t svbcax[_s16](svint16_t op1, svint16_t op2, svint16_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<short> BitwiseClearXor(Vector<short> xor, Vector<short> value, Vector<short> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svint32_t svbcax[_s32](svint32_t op1, svint32_t op2, svint32_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<int> BitwiseClearXor(Vector<int> xor, Vector<int> value, Vector<int> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svint64_t svbcax[_s64](svint64_t op1, svint64_t op2, svint64_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<long> BitwiseClearXor(Vector<long> xor, Vector<long> value, Vector<long> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svint8_t svbcax[_s8](svint8_t op1, svint8_t op2, svint8_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<sbyte> BitwiseClearXor(Vector<sbyte> xor, Vector<sbyte> value, Vector<sbyte> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svuint16_t svbcax[_u16](svuint16_t op1, svuint16_t op2, svuint16_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<ushort> BitwiseClearXor(Vector<ushort> xor, Vector<ushort> value, Vector<ushort> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svuint32_t svbcax[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<uint> BitwiseClearXor(Vector<uint> xor, Vector<uint> value, Vector<uint> mask) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svuint64_t svbcax[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<ulong> BitwiseClearXor(Vector<ulong> xor, Vector<ulong> value, Vector<ulong> mask) { throw new PlatformNotSupportedException(); }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Numerics;

namespace System.Runtime.Intrinsics.Arm
{
/// <summary>
/// This class provides access to the ARM SVE hardware instructions via intrinsics
/// </summary>
[Intrinsic]
[CLSCompliant(false)]
[Experimental(Experimentals.ArmSveDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public abstract class Sve2 : Sve
{
internal Sve2() { }

public static new bool IsSupported { get => IsSupported; }

[Intrinsic]
public new abstract class Arm64 : Sve.Arm64
{
internal Arm64() { }

public static new bool IsSupported { get => IsSupported; }
}

// Bitwise clear and exclusive OR

/// <summary>
/// svuint8_t svbcax[_u8](svuint8_t op1, svuint8_t op2, svuint8_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<byte> BitwiseClearXor(Vector<byte> xor, Vector<byte> value, Vector<byte> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svint16_t svbcax[_s16](svint16_t op1, svint16_t op2, svint16_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<short> BitwiseClearXor(Vector<short> xor, Vector<short> value, Vector<short> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svint32_t svbcax[_s32](svint32_t op1, svint32_t op2, svint32_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<int> BitwiseClearXor(Vector<int> xor, Vector<int> value, Vector<int> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svint64_t svbcax[_s64](svint64_t op1, svint64_t op2, svint64_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<long> BitwiseClearXor(Vector<long> xor, Vector<long> value, Vector<long> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svint8_t svbcax[_s8](svint8_t op1, svint8_t op2, svint8_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<sbyte> BitwiseClearXor(Vector<sbyte> xor, Vector<sbyte> value, Vector<sbyte> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svuint16_t svbcax[_u16](svuint16_t op1, svuint16_t op2, svuint16_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<ushort> BitwiseClearXor(Vector<ushort> xor, Vector<ushort> value, Vector<ushort> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svuint32_t svbcax[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<uint> BitwiseClearXor(Vector<uint> xor, Vector<uint> value, Vector<uint> mask) => BitwiseClearXor(xor, value, mask);

/// <summary>
/// svuint64_t svbcax[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3)
/// BCAX Ztied1.D, Ztied1.D, Zop2.D, Zop3.D
/// </summary>
public static unsafe Vector<ulong> BitwiseClearXor(Vector<ulong> xor, Vector<ulong> value, Vector<ulong> mask) => BitwiseClearXor(xor, value, mask);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5971,6 +5971,28 @@ internal Arm64() { }
public static System.Numerics.Vector<ulong> ZipLow(System.Numerics.Vector<ulong> left, System.Numerics.Vector<ulong> right) { throw null; }
}

[System.CLSCompliantAttribute(false)]
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public abstract partial class Sve2 : System.Runtime.Intrinsics.Arm.Sve
{
internal Sve2() { }
public static new bool IsSupported { get { throw null; } }
public new abstract partial class Arm64 : System.Runtime.Intrinsics.Arm.Sve.Arm64
{
internal Arm64() { }
public static new bool IsSupported { get { throw null; } }
}

public static System.Numerics.Vector<byte> BitwiseClearXor(System.Numerics.Vector<byte> xor, System.Numerics.Vector<byte> value, System.Numerics.Vector<byte> mask) { throw null; }
public static System.Numerics.Vector<short> BitwiseClearXor(System.Numerics.Vector<short> xor, System.Numerics.Vector<short> value, System.Numerics.Vector<short> mask) { throw null; }
public static System.Numerics.Vector<int> BitwiseClearXor(System.Numerics.Vector<int> xor, System.Numerics.Vector<int> value, System.Numerics.Vector<int> mask) { throw null; }
public static System.Numerics.Vector<long> BitwiseClearXor(System.Numerics.Vector<long> xor, System.Numerics.Vector<long> value, System.Numerics.Vector<long> mask) { throw null; }
public static System.Numerics.Vector<sbyte> BitwiseClearXor(System.Numerics.Vector<sbyte> xor, System.Numerics.Vector<sbyte> value, System.Numerics.Vector<sbyte> mask) { throw null; }
public static System.Numerics.Vector<ushort> BitwiseClearXor(System.Numerics.Vector<ushort> xor, System.Numerics.Vector<ushort> value, System.Numerics.Vector<ushort> mask) { throw null; }
public static System.Numerics.Vector<uint> BitwiseClearXor(System.Numerics.Vector<uint> xor, System.Numerics.Vector<uint> value, System.Numerics.Vector<uint> mask) { throw null; }
public static System.Numerics.Vector<ulong> BitwiseClearXor(System.Numerics.Vector<ulong> xor, System.Numerics.Vector<ulong> value, System.Numerics.Vector<ulong> mask) { throw null; }
}

public enum SveMaskPattern : byte
{
LargestPowerOf2 = 0, // The largest power of 2.
Expand Down
Loading
Loading