diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index c568a3bad49774..0061417decdb92 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -588,7 +588,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { assert(instrIsRMW); - insScalableOpts sopt; + insScalableOpts sopt = INS_SCALABLE_OPTS_NONE; + bool hasShift = false; switch (intrinEmbMask.id) { @@ -601,17 +602,34 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { assert(emitter::optGetSveInsOpt(op2Size) == INS_OPTS_SCALABLE_D); sopt = INS_SCALABLE_OPTS_WIDE; - break; } - - FALLTHROUGH; + break; } + case NI_Sve_ShiftRightArithmeticForDivide: + hasShift = true; + break; + default: - sopt = INS_SCALABLE_OPTS_NONE; break; } + auto emitInsHelper = [&](regNumber reg1, regNumber reg2, regNumber reg3) { + if (hasShift) + { + HWIntrinsicImmOpHelper helper(this, intrinEmbMask.op2, op2->AsHWIntrinsic()); + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + GetEmitter()->emitInsSve_R_R_I(insEmbMask, emitSize, reg1, reg2, helper.ImmValue(), opt, + sopt); + } + } + else + { + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, reg1, reg2, reg3, opt, sopt); + } + }; + if (intrin.op3->IsVectorZero()) { // If `falseReg` is zero, then move the first operand of `intrinEmbMask` in the @@ -622,7 +640,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand // and `embMaskOp2Reg` is the second operand. - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt, sopt); + emitInsHelper(targetReg, maskReg, embMaskOp2Reg); } else if (targetReg != falseReg) { @@ -636,8 +654,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { // If the embedded instruction supports optional mask operation, use the "unpredicated" // version of the instruction, followed by "sel" to select the active lanes. - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, embMaskOp1Reg, - embMaskOp2Reg, opt, sopt); + emitInsHelper(targetReg, embMaskOp1Reg, embMaskOp2Reg); } else { @@ -651,8 +668,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, embMaskOp1Reg); - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, - opt, sopt); + emitInsHelper(targetReg, maskReg, embMaskOp2Reg); } GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg, @@ -669,13 +685,13 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand // and `embMaskOp2Reg` is the second operand. - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt, sopt); + emitInsHelper(targetReg, maskReg, embMaskOp2Reg); } else { // Just perform the actual "predicated" operation so that `targetReg` is the first operand // and `embMaskOp2Reg` is the second operand. - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt, sopt); + emitInsHelper(targetReg, maskReg, embMaskOp2Reg); } break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 688691124eab6d..608dd2f3cbb9ce 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -201,6 +201,7 @@ HARDWARE_INTRINSIC(Sve, SaturatingIncrementByActiveElementCount, HARDWARE_INTRINSIC(Sve, Scale, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fscale, INS_sve_fscale}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, ShiftLeftLogical, -1, -1, false, {INS_sve_lsl, INS_sve_lsl, INS_sve_lsl, INS_sve_lsl, INS_sve_lsl, INS_sve_lsl, INS_sve_lsl, INS_sve_lsl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, ShiftRightArithmetic, -1, -1, false, {INS_sve_asr, INS_invalid, INS_sve_asr, INS_invalid, INS_sve_asr, INS_invalid, INS_sve_asr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, ShiftRightArithmeticForDivide, -1, -1, false, {INS_sve_asrd, INS_invalid, INS_sve_asrd, INS_invalid, INS_sve_asrd, INS_invalid, INS_sve_asrd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_HasImmediateOperand) HARDWARE_INTRINSIC(Sve, ShiftRightLogical, -1, -1, false, {INS_invalid, INS_sve_lsr, INS_invalid, INS_sve_lsr, INS_invalid, INS_sve_lsr, INS_invalid, INS_sve_lsr, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, SignExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxth, INS_invalid, INS_sve_sxth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SignExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxtw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index d1239dc8370072..65ecbc85a9bda0 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -3369,6 +3369,8 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) // Handle op2 if (op2->OperIsHWIntrinsic()) { + const GenTreeHWIntrinsic* embOp = op2->AsHWIntrinsic(); + if (IsInvariantInRange(op2, node) && op2->isEmbeddedMaskingCompatibleHWIntrinsic()) { uint32_t maskSize = genTypeSize(node->GetSimdBaseType()); @@ -3384,7 +3386,6 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { // Else check if this operation has an auxiliary type that matches the // mask size. - GenTreeHWIntrinsic* embOp = op2->AsHWIntrinsic(); // For now, make sure that we get here only for intrinsics that we are // sure about to rely on auxiliary type's size. @@ -3401,6 +3402,17 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) } } } + + // Handle intrinsics with embedded masks and immediate operands + // (For now, just handle ShiftRightArithmeticForDivide specifically) + if (embOp->GetHWIntrinsicId() == NI_Sve_ShiftRightArithmeticForDivide) + { + assert(embOp->GetOperandCount() == 2); + if (embOp->Op(2)->IsCnsIntOrI()) + { + MakeSrcContained(op2, embOp->Op(2)); + } + } } // Handle op3 diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index c344596f632e55..682987771ed932 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -1906,6 +1906,19 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou else { assert((numArgs == 1) || (numArgs == 2) || (numArgs == 3)); + + // Special handling for ShiftRightArithmeticForDivide: + // We might need an additional register to hold branch targets into the switch table + // that encodes the immediate + if (intrinEmb.id == NI_Sve_ShiftRightArithmeticForDivide) + { + assert(embOp2Node->GetOperandCount() == 2); + if (!embOp2Node->Op(2)->isContainedIntOrIImmed()) + { + buildInternalIntRegisterDefForNode(embOp2Node); + } + } + tgtPrefUse = BuildUse(embOp2Node->Op(1)); srcCount += 1; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 371da71f844edc..f3d0483b22b4e5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -5858,6 +5858,45 @@ internal Arm64() { } public static unsafe Vector ShiftRightArithmetic(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// Arithmetic shift right for divide by immediate + + /// + /// svint16_t svasrd[_n_s16]_m(svbool_t pg, svint16_t op1, uint64_t imm2) + /// ASRD Ztied1.H, Pg/M, Ztied1.H, #imm2 + /// svint16_t svasrd[_n_s16]_x(svbool_t pg, svint16_t op1, uint64_t imm2) + /// ASRD Ztied1.H, Pg/M, Ztied1.H, #imm2 + /// svint16_t svasrd[_n_s16]_z(svbool_t pg, svint16_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte control) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svasrd[_n_s32]_m(svbool_t pg, svint32_t op1, uint64_t imm2) + /// ASRD Ztied1.S, Pg/M, Ztied1.S, #imm2 + /// svint32_t svasrd[_n_s32]_x(svbool_t pg, svint32_t op1, uint64_t imm2) + /// ASRD Ztied1.S, Pg/M, Ztied1.S, #imm2 + /// svint32_t svasrd[_n_s32]_z(svbool_t pg, svint32_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte control) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svasrd[_n_s64]_m(svbool_t pg, svint64_t op1, uint64_t imm2) + /// ASRD Ztied1.D, Pg/M, Ztied1.D, #imm2 + /// svint64_t svasrd[_n_s64]_x(svbool_t pg, svint64_t op1, uint64_t imm2) + /// ASRD Ztied1.D, Pg/M, Ztied1.D, #imm2 + /// svint64_t svasrd[_n_s64]_z(svbool_t pg, svint64_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte control) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svasrd[_n_s8]_m(svbool_t pg, svint8_t op1, uint64_t imm2) + /// ASRD Ztied1.B, Pg/M, Ztied1.B, #imm2 + /// svint8_t svasrd[_n_s8]_x(svbool_t pg, svint8_t op1, uint64_t imm2) + /// ASRD Ztied1.B, Pg/M, Ztied1.B, #imm2 + /// svint8_t svasrd[_n_s8]_z(svbool_t pg, svint8_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(8))] byte control) { throw new PlatformNotSupportedException(); } + + /// Logical shift right /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 39d8dde224aa9d..82fbf7c9fd43f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -5902,6 +5902,45 @@ internal Arm64() { } public static unsafe Vector ShiftRightArithmetic(Vector left, Vector right) => ShiftRightArithmetic(left, right); + /// Arithmetic shift right for divide by immediate + + /// + /// svint16_t svasrd[_n_s16]_m(svbool_t pg, svint16_t op1, uint64_t imm2) + /// ASRD Ztied1.H, Pg/M, Ztied1.H, #imm2 + /// svint16_t svasrd[_n_s16]_x(svbool_t pg, svint16_t op1, uint64_t imm2) + /// ASRD Ztied1.H, Pg/M, Ztied1.H, #imm2 + /// svint16_t svasrd[_n_s16]_z(svbool_t pg, svint16_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte control) => ShiftRightArithmeticForDivide(value, control); + + /// + /// svint32_t svasrd[_n_s32]_m(svbool_t pg, svint32_t op1, uint64_t imm2) + /// ASRD Ztied1.S, Pg/M, Ztied1.S, #imm2 + /// svint32_t svasrd[_n_s32]_x(svbool_t pg, svint32_t op1, uint64_t imm2) + /// ASRD Ztied1.S, Pg/M, Ztied1.S, #imm2 + /// svint32_t svasrd[_n_s32]_z(svbool_t pg, svint32_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte control) => ShiftRightArithmeticForDivide(value, control); + + /// + /// svint64_t svasrd[_n_s64]_m(svbool_t pg, svint64_t op1, uint64_t imm2) + /// ASRD Ztied1.D, Pg/M, Ztied1.D, #imm2 + /// svint64_t svasrd[_n_s64]_x(svbool_t pg, svint64_t op1, uint64_t imm2) + /// ASRD Ztied1.D, Pg/M, Ztied1.D, #imm2 + /// svint64_t svasrd[_n_s64]_z(svbool_t pg, svint64_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte control) => ShiftRightArithmeticForDivide(value, control); + + /// + /// svint8_t svasrd[_n_s8]_m(svbool_t pg, svint8_t op1, uint64_t imm2) + /// ASRD Ztied1.B, Pg/M, Ztied1.B, #imm2 + /// svint8_t svasrd[_n_s8]_x(svbool_t pg, svint8_t op1, uint64_t imm2) + /// ASRD Ztied1.B, Pg/M, Ztied1.B, #imm2 + /// svint8_t svasrd[_n_s8]_z(svbool_t pg, svint8_t op1, uint64_t imm2) + /// + public static unsafe Vector ShiftRightArithmeticForDivide(Vector value, [ConstantExpected(Min = 1, Max = (byte)(8))] byte control) => ShiftRightArithmeticForDivide(value, control); + + /// Logical shift right /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 1904b956195d07..4e6c684ce0759c 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -5036,6 +5036,10 @@ internal Arm64() { } public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ShiftRightArithmeticForDivide(System.Numerics.Vector value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte control) { throw null; } + public static System.Numerics.Vector ShiftRightArithmeticForDivide(System.Numerics.Vector value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte control) { throw null; } + public static System.Numerics.Vector ShiftRightArithmeticForDivide(System.Numerics.Vector value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte control) { throw null; } + public static System.Numerics.Vector ShiftRightArithmeticForDivide(System.Numerics.Vector value, [ConstantExpected(Min = 1, Max = (byte)(8))] byte control) { throw null; } public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 0719ba73f68c5e..25e646b7b42168 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -3793,6 +3793,11 @@ ("SveVecBinOpDifferentTypesTest.template", new Dictionary { ["TestName"] = "Sve_ShiftRightArithmetic_sbyte_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.ShiftRight(left[i], right[(i * sizeof(sbyte)) / sizeof(ulong)]) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(left[i], right[(i * sizeof(sbyte)) / sizeof(ulong)])"}), ("SveVecBinOpDifferentTypesTest.template", new Dictionary { ["TestName"] = "Sve_ShiftRightArithmetic_short_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.ShiftRight(left[i], right[(i * sizeof(short)) / sizeof(ulong)]) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(left[i], right[(i * sizeof(short)) / sizeof(ulong)])"}), ("SveVecBinOpDifferentTypesTest.template", new Dictionary { ["TestName"] = "Sve_ShiftRightArithmetic_int_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.ShiftRight(left[i], right[(i * sizeof(int)) / sizeof(ulong)]) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(left[i], right[(i * sizeof(int)) / sizeof(ulong)])"}), + + ("SveVecImmUnOpTest.template", new Dictionary {["TestName"] = "Sve_ShiftRightArithmeticForDivide_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmeticForDivide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["InvalidImm"] = "0", ["Imm"] = "(TestLibrary.Generator.GetByte() % 8) + 1", ["ValidateIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm)"}), + ("SveVecImmUnOpTest.template", new Dictionary {["TestName"] = "Sve_ShiftRightArithmeticForDivide_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmeticForDivide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["InvalidImm"] = "0", ["Imm"] = "(TestLibrary.Generator.GetByte() % 16) + 1", ["ValidateIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm)"}), + ("SveVecImmUnOpTest.template", new Dictionary {["TestName"] = "Sve_ShiftRightArithmeticForDivide_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmeticForDivide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["InvalidImm"] = "0", ["Imm"] = "(TestLibrary.Generator.GetByte() % 32) + 1", ["ValidateIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm)"}), + ("SveVecImmUnOpTest.template", new Dictionary {["TestName"] = "Sve_ShiftRightArithmeticForDivide_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightArithmeticForDivide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["InvalidImm"] = "0", ["Imm"] = "(TestLibrary.Generator.GetByte() % 64) + 1", ["ValidateIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(firstOp[i], (ulong)imm)"}), ("SveVecBinOpDifferentTypesTest.template", new Dictionary { ["TestName"] = "Sve_ShiftRightLogical_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ShiftRight(left[i], (ulong)right[i]) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(left[i], (ulong)right[i])"}), ("SveVecBinOpDifferentTypesTest.template", new Dictionary { ["TestName"] = "Sve_ShiftRightLogical_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.ShiftRight(left[i], (ulong)right[i]) != result[i]", ["GetIterResult"] = "Helpers.ShiftRight(left[i], (ulong)right[i])"}),