diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 250a23904944a..abcd70d040f0b 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -6922,9 +6922,12 @@ void CodeGen::genArm64EmitterUnitTests() #ifdef ALL_ARM64_EMITTER_UNIT_TESTS // - // R_R fmov/fcmp/fcvt + // R_R cmeq/fmov/fcmp/fcvt // + // cmeq scalar + theEmitter->emitIns_R_R(INS_cmeq, EA_8BYTE, REG_V0, REG_V1); + // fmov to vector to vector theEmitter->emitIns_Mov(INS_fmov, EA_8BYTE, REG_V0, REG_V2, /* canSkip */ false); theEmitter->emitIns_Mov(INS_fmov, EA_4BYTE, REG_V1, REG_V3, /* canSkip */ false); diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 51e9afc074398..ff4e0b2d3c285 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1657,7 +1657,7 @@ void CodeGen::genConsumeRegs(GenTree* tree) #ifdef FEATURE_SIMD // (In)Equality operation that produces bool result, when compared // against Vector zero, marks its Vector Zero operand as contained. - assert(tree->OperIsLeaf() || tree->IsSIMDZero()); + assert(tree->OperIsLeaf() || tree->IsSIMDZero() || tree->IsVectorZero()); #else assert(tree->OperIsLeaf()); #endif diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 51e02c5c26895..3163b29dc6ae1 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -4732,19 +4732,19 @@ void emitter::emitIns_R_R( assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); - if (isValidVectorDatasize(size)) + if (insOptsAnyArrangement(opt)) { // Vector operation - assert(insOptsAnyArrangement(opt)); + assert(isValidVectorDatasize(size)); assert(isValidArrangement(size, opt)); elemsize = optGetElemsize(opt); fmt = IF_DV_2M; } else { - NYI("Untested"); // Scalar operation - assert(size == EA_8BYTE); // Only Double supported + assert(size == EA_8BYTE); + assert(insOptsNone(opt)); fmt = IF_DV_2L; } break; @@ -12971,6 +12971,11 @@ void emitter::emitDispIns( emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } + if (ins == INS_fcmeq) + { + printf(", "); + emitDispImm(0, false); + } break; case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) @@ -12990,6 +12995,11 @@ void emitter::emitDispIns( emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } + if (ins == INS_cmeq) + { + printf(", "); + emitDispImm(0, false); + } break; case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar) @@ -13126,6 +13136,11 @@ void emitter::emitDispIns( emitDispReg(id->idReg1(), size, true); emitDispReg(id->idReg2(), size, false); } + if (fmt == IF_DV_2L && ins == INS_cmeq) + { + printf(", "); + emitDispImm(0, false); + } break; case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 59c47e4246c7e..c1c5d26ac7c1b 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17732,6 +17732,20 @@ bool GenTree::isContainableHWIntrinsic() const return true; } + default: + { + return false; + } + } +#elif TARGET_ARM64 + switch (AsHWIntrinsic()->GetHWIntrinsicId()) + { + case NI_Vector64_get_Zero: + case NI_Vector128_get_Zero: + { + return true; + } + default: { return false; diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index e7a03d26547d3..8cab63e505b5f 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1704,6 +1704,8 @@ struct GenTree inline bool IsIntegralConst(ssize_t constVal) const; inline bool IsIntegralConstVector(ssize_t constVal) const; inline bool IsSIMDZero() const; + inline bool IsFloatPositiveZero() const; + inline bool IsVectorZero() const; inline bool IsBoxedValue(); @@ -2097,7 +2099,7 @@ struct GenTree inline bool IsCnsFltOrDbl() const; - inline bool IsCnsNonZeroFltOrDbl(); + inline bool IsCnsNonZeroFltOrDbl() const; bool IsIconHandle() const { @@ -7650,6 +7652,79 @@ inline bool GenTree::IsSIMDZero() const return false; } +//------------------------------------------------------------------- +// IsFloatPositiveZero: returns true if this is exactly a const float value of postive zero (+0.0) +// +// Returns: +// True if this represents a const floating-point value of exactly positive zero (+0.0). +// Will return false if the value is negative zero (-0.0). +// +inline bool GenTree::IsFloatPositiveZero() const +{ + return !(IsCnsNonZeroFltOrDbl()); +} + +//------------------------------------------------------------------- +// IsVectorZero: returns true if this is an integral or floating-point (SIMD or HW intrinsic) vector +// with all its elements equal to zero. +// +// Returns: +// True if this represents an integral or floating-point const (SIMD or HW intrinsic) vector with all its elements +// equal to zero. +// +// TODO: We already have IsSIMDZero() and IsIntegralConstVector(0), +// however, IsSIMDZero() does not cover hardware intrinsics, and IsIntegralConstVector(0) does not cover floating +// point. In order to not risk adverse behaviour by modifying those, this function 'IsVectorZero' was introduced. +// At some point, it makes sense to normalize this logic to be a single function call rather than have several +// separate ones; preferably this one. +inline bool GenTree::IsVectorZero() const +{ +#ifdef FEATURE_SIMD + if (gtOper == GT_SIMD) + { + const GenTreeSIMD* node = AsSIMD(); + + if (node->GetSIMDIntrinsicId() == SIMDIntrinsicInit) + { + return (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero()); + } + } +#endif + +#ifdef FEATURE_HW_INTRINSICS + if (gtOper == GT_HWINTRINSIC) + { + const GenTreeHWIntrinsic* node = AsHWIntrinsic(); + const var_types simdBaseType = node->GetSimdBaseType(); + + if (varTypeIsIntegral(simdBaseType) || varTypeIsFloating(simdBaseType)) + { + const NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); + + if (node->GetOperandCount() == 0) + { +#if defined(TARGET_XARCH) + return (intrinsicId == NI_Vector128_get_Zero) || (intrinsicId == NI_Vector256_get_Zero); +#elif defined(TARGET_ARM64) + return (intrinsicId == NI_Vector64_get_Zero) || (intrinsicId == NI_Vector128_get_Zero); +#endif // !TARGET_XARCH && !TARGET_ARM64 + } + else if ((node->GetOperandCount() == 1) && + (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero())) + { +#if defined(TARGET_XARCH) + return (intrinsicId == NI_Vector128_Create) || (intrinsicId == NI_Vector256_Create); +#elif defined(TARGET_ARM64) + return (intrinsicId == NI_Vector64_Create) || (intrinsicId == NI_Vector128_Create); +#endif // !TARGET_XARCH && !TARGET_ARM64 + } + } + } +#endif // FEATURE_HW_INTRINSICS + + return false; +} + inline bool GenTree::IsBoxedValue() { assert(gtOper != GT_BOX || AsBox()->BoxOp() != nullptr); @@ -8328,7 +8403,7 @@ inline bool GenTree::IsCnsFltOrDbl() const return OperGet() == GT_CNS_DBL; } -inline bool GenTree::IsCnsNonZeroFltOrDbl() +inline bool GenTree::IsCnsNonZeroFltOrDbl() const { if (OperGet() == GT_CNS_DBL) { diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 706b988f049e5..e4b9a1326680c 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -496,6 +496,29 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); break; + case NI_AdvSimd_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqualScalar: + if (intrin.op1->isContained()) + { + assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); + assert(intrin.op1->IsVectorZero()); + + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt); + } + else if (intrin.op2->isContained()) + { + assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); + assert(intrin.op2->IsVectorZero()); + + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); + } + else + { + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); + } + break; + case NI_AdvSimd_AbsoluteCompareLessThan: case NI_AdvSimd_AbsoluteCompareLessThanOrEqual: case NI_AdvSimd_CompareLessThan: diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 4b2e3fa132ad7..e119a38948a05 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -240,7 +240,7 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) @@ -492,8 +492,8 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar) diff --git a/src/coreclr/jit/instrsarm64.h b/src/coreclr/jit/instrsarm64.h index c89b006a41897..d4e7ef5b10c8d 100644 --- a/src/coreclr/jit/instrsarm64.h +++ b/src/coreclr/jit/instrsarm64.h @@ -312,8 +312,8 @@ INST4(neg, "neg", 0, IF_EN4G, 0x4B0003E0, 0x4B0003E0, INST4(cmeq, "cmeq", 0, IF_EN4H, 0x7EE08C00, 0x2E208C00, 0x5E209800, 0x0E209800) // cmeq Vd,Vn,Vm DV_3E 01111110111mmmmm 100011nnnnnddddd 7EE0 8C00 Vd,Vn,Vm (scalar) // cmeq Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100011nnnnnddddd 2E20 8C00 Vd,Vn,Vm (vector) - // cmeq Vd,Vn DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn (scalar) - // cmeq Vd,Vn DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn (vector) + // cmeq Vd,Vn,#0 DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn,#0 (scalar - with zero) + // cmeq Vd,Vn,#0 DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn,#0 (vector - with zero) INST4(cmge, "cmge", 0, IF_EN4H, 0x5EE03C00, 0x0E203C00, 0x7E208800, 0x2E208800) // cmge Vd,Vn,Vm DV_3E 01011110111mmmmm 001111nnnnnddddd 5EE0 3C00 Vd,Vn,Vm (scalar) @@ -331,8 +331,8 @@ INST4(cmgt, "cmgt", 0, IF_EN4H, 0x5EE03400, 0x0E203400, INST4(fcmeq, "fcmeq", 0, IF_EN4I, 0x5E20E400, 0x0E20E400, 0x5EA0D800, 0x0EA0D800) // fcmeq Vd,Vn,Vm DV_3D 010111100X1mmmmm 111001nnnnnddddd 5E20 E400 Vd Vn Vm (scalar) // fcmeq Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111001nnnnnddddd 0E20 E400 Vd,Vn,Vm (vector) - // fcmeq Vd,Vn DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn (scalar) - // fcmeq Vd,Vn DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn (vector) + // fcmeq Vd,Vn,#0 DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn,#0 (scalar - with zero) + // fcmeq Vd,Vn,#0 DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn,#0 (vector - with zero) INST4(fcmge, "fcmge", 0, IF_EN4I, 0x7E20E400, 0x2E20E400, 0x7EA0C800, 0x2EA0C800) // fcmge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111001nnnnnddddd 7E20 E400 Vd Vn Vm (scalar) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index e4ba37cffb1d5..eb07f114c1799 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1853,6 +1853,21 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) MakeSrcContained(node, intrin.op4); break; + case NI_AdvSimd_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqual: + case NI_AdvSimd_Arm64_CompareEqualScalar: + { + if (intrin.op1->IsVectorZero()) + { + MakeSrcContained(node, intrin.op1); + } + else if (intrin.op2->IsVectorZero()) + { + MakeSrcContained(node, intrin.op2); + } + break; + } + case NI_Vector64_CreateScalarUnsafe: case NI_Vector128_CreateScalarUnsafe: case NI_AdvSimd_DuplicateToVector64: diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 73b971ec5932f..796a9e8126e6f 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -1091,55 +1091,52 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) } } } - else + else if (intrin.op2 != nullptr) { - if (intrin.op2 != nullptr) - { - // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg - // (i.e. a register that corresponds to read-modify-write operand) and one of them is the last use. + // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg + // (i.e. a register that corresponds to read-modify-write operand) and one of them is the last use. - assert(intrin.op1 != nullptr); + assert(intrin.op1 != nullptr); - bool forceOp2DelayFree = false; - if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement)) + bool forceOp2DelayFree = false; + if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement)) + { + if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal())) { - if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal())) - { - // If the index is not a constant and the object is not contained or is a local - // we will need a general purpose register to calculate the address - // internal register must not clobber input index - // TODO-Cleanup: An internal register will never clobber a source; this code actually - // ensures that the index (op2) doesn't interfere with the target. - buildInternalIntRegisterDefForNode(intrinsicTree); - forceOp2DelayFree = true; - } - - if (!intrin.op2->IsCnsIntOrI() && !intrin.op1->isContained()) - { - // If the index is not a constant or op1 is in register, - // we will use the SIMD temp location to store the vector. - var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16; - compiler->getSIMDInitTempVarNum(requiredSimdTempType); - } + // If the index is not a constant and the object is not contained or is a local + // we will need a general purpose register to calculate the address + // internal register must not clobber input index + // TODO-Cleanup: An internal register will never clobber a source; this code actually + // ensures that the index (op2) doesn't interfere with the target. + buildInternalIntRegisterDefForNode(intrinsicTree); + forceOp2DelayFree = true; } - if (forceOp2DelayFree) - { - srcCount += BuildDelayFreeUses(intrin.op2); - } - else + if (!intrin.op2->IsCnsIntOrI() && !intrin.op1->isContained()) { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2); + // If the index is not a constant or op1 is in register, + // we will use the SIMD temp location to store the vector. + var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16; + compiler->getSIMDInitTempVarNum(requiredSimdTempType); } + } - if (intrin.op3 != nullptr) - { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3); + if (forceOp2DelayFree) + { + srcCount += BuildDelayFreeUses(intrin.op2); + } + else + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2); + } - if (intrin.op4 != nullptr) - { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4); - } + if (intrin.op3 != nullptr) + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3); + + if (intrin.op4 != nullptr) + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4); } } } diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index a48d7e7bdee57..d58f1996091fa 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3078,6 +3078,15 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates) return 1; } +#ifdef TARGET_ARM64 + // Must happen before OperIsHWIntrinsic case, + // but this occurs when a vector zero node is marked as contained. + if (node->IsVectorZero()) + { + return 0; + } +#endif + #if !defined(TARGET_64BIT) if (node->OperIs(GT_LONG)) { @@ -3164,6 +3173,14 @@ int LinearScan::BuildDelayFreeUses(GenTree* node, GenTree* rmwNode, regMaskTP ca { use = BuildUse(node, candidates); } +#ifdef TARGET_ARM64 + // Must happen before OperIsHWIntrinsic case, + // but this occurs when a vector zero node is marked as contained. + else if (node->IsVectorZero()) + { + return 0; + } +#endif #ifdef FEATURE_HW_INTRINSICS else if (node->OperIsHWIntrinsic()) { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs new file mode 100644 index 0000000000000..7535cd334d962 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs @@ -0,0 +1,559 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +class Program +{ + // CompareEqual + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Byte_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_SByte_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt16_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int16_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt32_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int32_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Single_Zero(Vector64 left) + { + return AdvSimd.CompareEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Byte_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_SByte_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt16_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int16_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt32_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int32_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Single_Zero(Vector128 left) + { + return AdvSimd.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareEqualScalar(left, Vector64.Zero); + } + + // CompareEqual Swapped + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Byte_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_SByte_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt16_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int16_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_UInt32_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Int32_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareEqual_Vector64_Single_Zero_Swapped(Vector64 right) + { + return AdvSimd.CompareEqual(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Byte_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_SByte_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt16_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int16_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_UInt32_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Int32_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareEqual_Vector128_Single_Zero_Swapped(Vector128 right) + { + return AdvSimd.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero_Swapped(Vector128 right) + { + return AdvSimd.Arm64.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero_Swapped(Vector128 right) + { + return AdvSimd.Arm64.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero_Swapped(Vector128 right) + { + return AdvSimd.Arm64.CompareEqual(Vector128.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero_Swapped(Vector64 right) + { + return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); + } + + // Validation + + unsafe static bool ValidateResult_Vector64(Vector64 result, T expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (8 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue)) + { + succeeded = false; + } + } + + return succeeded; + } + + unsafe static bool ValidateResult_Vector64(Vector64 result, Vector64 expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (8 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue.GetElement(i))) + { + succeeded = false; + } + } + + return succeeded; + } + + unsafe static bool ValidateResult_Vector128(Vector128 result, T expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (16 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue)) + { + succeeded = false; + } + } + + return succeeded; + } + + unsafe static bool ValidateResult_Vector128(Vector128 result, Vector128 expectedElementValue) where T : unmanaged + { + var succeeded = true; + + for (var i = 0; i < (16 / sizeof(T)); i++) + { + if (!result.GetElement(i).Equals(expectedElementValue.GetElement(i))) + { + succeeded = false; + } + } + + return succeeded; + } + + static int Tests_AdvSimd() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Byte_Zero(Vector64.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_SByte_Zero(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt16_Zero(Vector64.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int16_Zero(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt32_Zero(Vector64.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int32_Zero(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Single_Zero(Vector64.Zero), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Byte_Zero(Vector128.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_SByte_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt16_Zero(Vector128.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int16_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt32_Zero(Vector128.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int32_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Single_Zero(Vector128.Zero), Single.NaN)) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Tests_AdvSimd_Swapped() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Byte_Zero_Swapped(Vector64.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_SByte_Zero_Swapped(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt16_Zero_Swapped(Vector64.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int16_Zero_Swapped(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_UInt32_Zero_Swapped(Vector64.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Int32_Zero_Swapped(Vector64.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareEqual_Vector64_Single_Zero_Swapped(Vector64.Zero), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Byte_Zero_Swapped(Vector128.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_SByte_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt16_Zero_Swapped(Vector128.Zero), UInt16.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int16_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_UInt32_Zero_Swapped(Vector128.Zero), UInt32.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Int32_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareEqual_Vector128_Single_Zero_Swapped(Vector128.Zero), Single.NaN)) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Tests_AdvSimd_Arm64() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero(Vector128.Zero), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero(Vector128.Zero), UInt64.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero(Vector64.Zero), Vector64.CreateScalar(Single.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero(Vector64.Zero), Vector64.CreateScalar(Double.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero(Vector64.Zero), Vector64.CreateScalar(UInt64.MaxValue))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero(Vector64.Zero), Vector64.CreateScalar(-1L))) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Tests_AdvSimd_Arm64_Swapped() + { + var result = 100; + + // Begin CompareEqual Tests + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Double_Zero_Swapped(Vector128.Zero), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_UInt64_Zero_Swapped(Vector128.Zero), UInt64.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareEqual_Vector128_Int64_Zero_Swapped(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Single_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(Single.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Double_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(Double.NaN))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_UInt64_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(UInt64.MaxValue))) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero_Swapped(Vector64.Zero), Vector64.CreateScalar(-1L))) + result = -1; + + // End CompareEqual Tests + + return result; + } + + static int Main(string[] args) + { + var result = 100; + + if (AdvSimd.IsSupported) + { + Console.WriteLine("Testing AdvSimd"); + + if (result != -1) + { + result = Tests_AdvSimd(); + } + if (result != -1) + { + result = Tests_AdvSimd_Swapped(); + } + + if (result == -1) + { + Console.WriteLine("AdvSimd Tests Failed"); + } + else + { + Console.WriteLine("AdvSimd Tests Passed"); + } + } + else + { + Console.WriteLine("Skipped AdvSimd Tests"); + } + + if (AdvSimd.Arm64.IsSupported) + { + Console.WriteLine("Testing AdvSimd_Arm64"); + + if (result != -1) + { + result = Tests_AdvSimd_Arm64(); + } + if (result != -1) + { + result = Tests_AdvSimd_Arm64_Swapped(); + } + + if (result == -1) + { + Console.WriteLine("AdvSimd_Arm64 Tests Failed"); + } + else + { + Console.WriteLine("AdvSimd_Arm64 Tests Passed"); + } + } + else + { + Console.WriteLine("Skipped AdvSimd_Arm64 Tests"); + } + + return result; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj new file mode 100644 index 0000000000000..bf6f589eb325b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.csproj @@ -0,0 +1,13 @@ + + + Exe + + + None + True + True + + + + +