diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 988dfa412c7d86..4da5ba3dd174f3 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -3963,10 +3963,6 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) break; case SIMDIntrinsicCast: - case SIMDIntrinsicConvertToSingle: - case SIMDIntrinsicConvertToInt32: - case SIMDIntrinsicConvertToDouble: - case SIMDIntrinsicConvertToInt64: genSIMDIntrinsicUnOp(simdNode); break; @@ -4051,10 +4047,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type case SIMDIntrinsicCast: result = INS_mov; break; - case SIMDIntrinsicConvertToInt32: - case SIMDIntrinsicConvertToInt64: - result = INS_fcvtzs; - break; case SIMDIntrinsicEqual: result = INS_fcmeq; break; @@ -4081,10 +4073,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type case SIMDIntrinsicCast: result = INS_mov; break; - case SIMDIntrinsicConvertToDouble: - case SIMDIntrinsicConvertToSingle: - result = isUnsigned ? INS_ucvtf : INS_scvtf; - break; case SIMDIntrinsicEqual: result = INS_cmeq; break; @@ -4232,11 +4220,7 @@ void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode) // void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode) { - assert((simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicCast) || - (simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicConvertToSingle) || - (simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicConvertToInt32) || - (simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicConvertToDouble) || - (simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicConvertToInt64)); + assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicCast); GenTree* op1 = simdNode->Op(1); var_types baseType = simdNode->GetSimdBaseType(); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 09dff5c7803f17..7edf65ebe2c377 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -19273,21 +19273,59 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, NamedIntrinsic intrinsic = NI_Illegal; +#if defined(TARGET_XARCH) + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); + } +#endif // TARGET_XARCH + switch (op) { #if defined(TARGET_XARCH) case GT_EQ: { + intrinsic = (simdSize == 32) ? NI_Vector256_op_Equality : NI_Vector128_op_Equality; + break; + } + + case GT_GE: + case GT_GT: + case GT_LE: + case GT_LT: + { + // We want to generate a comparison along the lines of + // GT_XX(op1, op2).As() == Vector128.AllBitsSet + + NamedIntrinsic getAllBitsSet = NI_Illegal; + if (simdSize == 32) { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); - assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); - intrinsic = NI_Vector256_op_Equality; + intrinsic = NI_Vector256_op_Equality; + getAllBitsSet = NI_Vector256_get_AllBitsSet; } else { - intrinsic = NI_Vector128_op_Equality; + intrinsic = NI_Vector128_op_Equality; + getAllBitsSet = NI_Vector128_get_AllBitsSet; + } + + op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_INT; + } + else if (simdBaseType == TYP_DOUBLE) + { + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_LONG; } + + op2 = gtNewSimdHWIntrinsicNode(simdBaseType, getAllBitsSet, simdBaseJitType, simdSize); break; } #elif defined(TARGET_ARM64) @@ -19296,6 +19334,45 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, intrinsic = (simdSize == 8) ? NI_Vector64_op_Equality : NI_Vector128_op_Equality; break; } + + case GT_GE: + case GT_GT: + case GT_LE: + case GT_LT: + { + // We want to generate a comparison along the lines of + // GT_XX(op1, op2).As() == Vector128.AllBitsSet + + NamedIntrinsic getAllBitsSet = NI_Illegal; + + if (simdSize == 8) + { + intrinsic = NI_Vector64_op_Equality; + getAllBitsSet = NI_Vector64_get_AllBitsSet; + } + else + { + intrinsic = NI_Vector128_op_Equality; + getAllBitsSet = NI_Vector128_get_AllBitsSet; + } + + op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_INT; + } + else if (simdBaseType == TYP_DOUBLE) + { + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_LONG; + } + + op2 = gtNewSimdHWIntrinsicNode(simdBaseType, getAllBitsSet, simdBaseJitType, simdSize); + break; + } #else #error Unsupported platform #endif // !TARGET_XARCH && !TARGET_ARM64 @@ -19335,24 +19412,81 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, NamedIntrinsic intrinsic = NI_Illegal; +#if defined(TARGET_XARCH) + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); + } +#endif // TARGET_XARCH + switch (op) { #if defined(TARGET_XARCH) - case GT_NE: + case GT_EQ: + case GT_GE: + case GT_GT: + case GT_LE: + case GT_LT: { - if (simdSize == 32) + // We want to generate a comparison along the lines of + // GT_XX(op1, op2).As() != Vector128.Zero + + intrinsic = (simdSize == 32) ? NI_Vector256_op_Inequality : NI_Vector128_op_Inequality; + + op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + + if (simdBaseType == TYP_FLOAT) { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); - assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); - intrinsic = NI_Vector256_op_Inequality; + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_INT; } - else + else if (simdBaseType == TYP_DOUBLE) { - intrinsic = NI_Vector128_op_Inequality; + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_LONG; } + + op2 = gtNewSimdZeroNode(simdBaseType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); + break; + } + + case GT_NE: + { + intrinsic = (simdSize == 32) ? NI_Vector256_op_Inequality : NI_Vector128_op_Inequality; break; } #elif defined(TARGET_ARM64) + case GT_EQ: + case GT_GE: + case GT_GT: + case GT_LE: + case GT_LT: + { + // We want to generate a comparison along the lines of + // GT_XX(op1, op2).As() != Vector128.Zero + + intrinsic = (simdSize == 8) ? NI_Vector64_op_Inequality : NI_Vector128_op_Inequality; + + op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_INT; + } + else if (simdBaseType == TYP_DOUBLE) + { + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_LONG; + } + + op2 = gtNewSimdZeroNode(simdBaseType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); + break; + } + case GT_NE: { intrinsic = (simdSize == 8) ? NI_Vector64_op_Inequality : NI_Vector128_op_Inequality; diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index ad86d58613dcd3..1ba2b7ae51271a 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -285,7 +285,7 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, bool isIsaSupported = comp->compHWIntrinsicDependsOn(isa) && comp->compSupportsHWIntrinsic(isa); - if (strcmp(methodName, "get_IsSupported") == 0) + if ((strcmp(methodName, "get_IsSupported") == 0) || (strcmp(methodName, "get_IsHardwareAccelerated") == 0)) { return isIsaSupported ? (comp->compExactlyDependsOn(isa) ? NI_IsSupported_True : NI_IsSupported_Dynamic) : NI_IsSupported_False; diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 1a08a26f78dc9e..69902ac7f30da8 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -475,19 +475,77 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector64_ConvertToDouble: case NI_Vector128_ConvertToDouble: + { + assert(sig->numArgs == 1); + assert((simdBaseType == TYP_LONG) || (simdBaseType == TYP_ULONG)); + + intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToDoubleScalar : NI_AdvSimd_Arm64_ConvertToDouble; + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_ConvertToInt32: case NI_Vector128_ConvertToInt32: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + op1 = impSIMDPopStack(retType); + retNode = + gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_ConvertToInt64: case NI_Vector128_ConvertToInt64: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + + intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_ConvertToSingle: case NI_Vector128_ConvertToSingle: + { + assert(sig->numArgs == 1); + assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_ConvertToUInt32: case NI_Vector128_ConvertToUInt32: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, simdBaseJitType, + simdSize); + break; + } + case NI_Vector64_ConvertToUInt64: case NI_Vector128_ConvertToUInt64: { assert(sig->numArgs == 1); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + assert(simdBaseType == TYP_DOUBLE); + + intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); break; } @@ -584,7 +642,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_EqualsAny: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_EQ, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -663,7 +727,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanAll: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_GT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -671,7 +741,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanAny: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_GT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -692,7 +768,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanOrEqualAll: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_GE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -700,7 +782,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanOrEqualAny: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_GE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -721,7 +809,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanAll: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_LT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -729,7 +823,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanAny: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_LT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -750,7 +850,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanOrEqualAll: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_LE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } @@ -758,7 +864,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanOrEqualAny: { assert(sig->numArgs == 2); - // TODO-ARM64-CQ: These intrinsics should be accelerated. + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_LE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); break; } diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 65879aff4024c3..9360ea2a4c369c 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -33,12 +33,12 @@ HARDWARE_INTRINSIC(Vector64, BitwiseAnd, HARDWARE_INTRINSIC(Vector64, BitwiseOr, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, Ceiling, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, ConditionalSelect, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToDouble, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, ConvertToDouble, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, Create, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Vector64, Divide, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -49,7 +49,6 @@ HARDWARE_INTRINSIC(Vector64, EqualsAny, HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, get_Count, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, get_IsHardwareAccelerated, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector64, GetElement, 8, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -119,12 +118,12 @@ HARDWARE_INTRINSIC(Vector128, BitwiseAnd, HARDWARE_INTRINSIC(Vector128, BitwiseOr, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -135,7 +134,6 @@ HARDWARE_INTRINSIC(Vector128, EqualsAny, HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, get_IsHardwareAccelerated, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GetLower, 16, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index ce66b6e6906040..827a5a8686f3c6 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -50,12 +50,12 @@ HARDWARE_INTRINSIC(Vector128, BitwiseAnd, HARDWARE_INTRINSIC(Vector128, BitwiseOr, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -66,7 +66,6 @@ HARDWARE_INTRINSIC(Vector128, EqualsAny, HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_IsHardwareAccelerated, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -134,12 +133,12 @@ HARDWARE_INTRINSIC(Vector256, BitwiseAnd, HARDWARE_INTRINSIC(Vector256, BitwiseOr, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, Ceiling, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, ConditionalSelect, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ConvertToDouble, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ConvertToInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ConvertToInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ConvertToSingle, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ConvertToUInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, ConvertToDouble, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToSingle, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, Create, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, Divide, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) @@ -150,7 +149,6 @@ HARDWARE_INTRINSIC(Vector256, EqualsAny, HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, get_Count, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, get_IsHardwareAccelerated, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, get_Zero, 32, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, GetElement, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) @@ -556,10 +554,10 @@ HARDWARE_INTRINSIC(AVX, CompareScalar, HARDWARE_INTRINSIC(AVX, ConvertToVector128Int32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, ConvertToVector128Single, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Single, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(AVX, ConvertToVector256Single, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, ConvertToVector256Double, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, ConvertToVector128Int32WithTruncation, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32WithTruncation, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32WithTruncation, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, Divide, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX, DotProduct, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(AVX, DuplicateEvenIndexed, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsldup, INS_movddup}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index 72c9734afc48b7..a0eceba4a8a0fa 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -835,12 +835,8 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_ConvertToDouble: case NI_Vector256_ConvertToDouble: - case NI_Vector128_ConvertToInt32: - case NI_Vector256_ConvertToInt32: case NI_Vector128_ConvertToInt64: case NI_Vector256_ConvertToInt64: - case NI_Vector128_ConvertToSingle: - case NI_Vector256_ConvertToSingle: case NI_Vector128_ConvertToUInt32: case NI_Vector256_ConvertToUInt32: case NI_Vector128_ConvertToUInt64: @@ -851,6 +847,40 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_ConvertToInt32: + case NI_Vector256_ConvertToInt32: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + intrinsic = (simdSize == 32) ? NI_AVX_ConvertToVector256Int32WithTruncation + : NI_SSE2_ConvertToVector128Int32WithTruncation; + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + break; + } + + case NI_Vector128_ConvertToSingle: + case NI_Vector256_ConvertToSingle: + { + assert(sig->numArgs == 1); + + if (simdBaseType == TYP_INT) + { + intrinsic = (simdSize == 32) ? NI_AVX_ConvertToVector256Single : NI_SSE2_ConvertToVector128Single; + + op1 = impSIMDPopStack(retType); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + } + else + { + // TODO-XARCH-CQ: These intrinsics should be accelerated + assert(simdBaseType == TYP_UINT); + } + break; + } + case NI_Vector128_Create: case NI_Vector256_Create: { @@ -991,7 +1021,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_EqualsAny: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_EQ, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1098,7 +1138,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_GreaterThanAll: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_GT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1106,7 +1156,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_GreaterThanAny: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_GT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1130,7 +1190,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_GreaterThanOrEqualAll: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_GE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1138,7 +1208,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_GreaterThanOrEqualAny: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_GE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1162,7 +1242,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_LessThanAll: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_LT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1170,7 +1260,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_LessThanAny: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_LT, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1194,7 +1294,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_LessThanOrEqualAll: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAllNode(GT_LE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } @@ -1202,7 +1312,17 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector256_LessThanOrEqualAny: { assert(sig->numArgs == 2); - // TODO-XARCH-CQ: These intrinsics should be accelerated + + if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + { + var_types simdType = getSIMDTypeForSize(simdSize); + + op2 = impSIMDPopStack(simdType); + op1 = impSIMDPopStack(simdType); + + retNode = gtNewSimdCmpOpAnyNode(GT_LE, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ false); + } break; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 57c3604899b7c5..5a662f54714d44 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -5398,7 +5398,7 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) if (result == NI_Illegal) { - if (strcmp(methodName, "get_IsSupported") == 0) + if ((strcmp(methodName, "get_IsSupported") == 0) || (strcmp(methodName, "get_IsHardwareAccelerated") == 0)) { // This allows the relevant code paths to be dropped as dead code even // on platforms where FEATURE_HW_INTRINSICS is not supported. diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 0f4ad4cdb04dd3..73b971ec5932fa 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -807,10 +807,6 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) { case SIMDIntrinsicInit: case SIMDIntrinsicCast: - case SIMDIntrinsicConvertToSingle: - case SIMDIntrinsicConvertToInt32: - case SIMDIntrinsicConvertToDouble: - case SIMDIntrinsicConvertToInt64: // No special handling required. break; diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index ea4c86639d5ec5..ce1de0b6f4fde1 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1955,54 +1955,6 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) case SIMDIntrinsicCast: break; - case SIMDIntrinsicConvertToSingle: - if (simdTree->GetSimdBaseType() == TYP_UINT) - { - // We need an internal register different from targetReg. - setInternalRegsDelayFree = true; - buildInternalFloatRegisterDefForNode(simdTree); - buildInternalFloatRegisterDefForNode(simdTree); - // We also need an integer register. - buildInternalIntRegisterDefForNode(simdTree); - } - break; - - case SIMDIntrinsicConvertToInt32: - break; - - case SIMDIntrinsicConvertToInt64: - // We need an internal register different from targetReg. - setInternalRegsDelayFree = true; - buildInternalFloatRegisterDefForNode(simdTree); - if (compiler->getSIMDSupportLevel() == SIMD_AVX2_Supported) - { - buildInternalFloatRegisterDefForNode(simdTree); - } - // We also need an integer register. - buildInternalIntRegisterDefForNode(simdTree); - break; - - case SIMDIntrinsicConvertToDouble: - // We need an internal register different from targetReg. - setInternalRegsDelayFree = true; - buildInternalFloatRegisterDefForNode(simdTree); -#ifdef TARGET_X86 - if (simdTree->GetSimdBaseType() == TYP_LONG) - { - buildInternalFloatRegisterDefForNode(simdTree); - buildInternalFloatRegisterDefForNode(simdTree); - } - else -#endif - if ((compiler->getSIMDSupportLevel() == SIMD_AVX2_Supported) || - (simdTree->GetSimdBaseType() == TYP_ULONG)) - { - buildInternalFloatRegisterDefForNode(simdTree); - } - // We also need an integer register. - buildInternalIntRegisterDefForNode(simdTree); - break; - case SIMDIntrinsicShuffleSSE2: // Second operand is an integer constant and marked as contained. assert(simdTree->Op(2)->isContainedIntOrIImmed()); diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 4e4bda2ee4a2a8..5bf3b20fc51f71 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -1200,10 +1200,6 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in case SIMDIntrinsicBitwiseAnd: case SIMDIntrinsicBitwiseOr: case SIMDIntrinsicCast: - case SIMDIntrinsicConvertToSingle: - case SIMDIntrinsicConvertToDouble: - case SIMDIntrinsicConvertToInt32: - case SIMDIntrinsicConvertToInt64: return true; default: @@ -2327,9 +2323,6 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, // Unary operators that take and return a Vector. case SIMDIntrinsicCast: - case SIMDIntrinsicConvertToSingle: - case SIMDIntrinsicConvertToDouble: - case SIMDIntrinsicConvertToInt32: { op1 = impSIMDPopStack(simdType, instMethod); @@ -2338,20 +2331,6 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, } break; - case SIMDIntrinsicConvertToInt64: - { -#ifdef TARGET_64BIT - op1 = impSIMDPopStack(simdType, instMethod); - - simdTree = gtNewSIMDNode(simdType, op1, simdIntrinsicID, simdBaseJitType, size); - retVal = simdTree; -#else - JITDUMP("SIMD Conversion to Int64 is not supported on this platform\n"); - return nullptr; -#endif - } - break; - case SIMDIntrinsicHWAccel: { GenTreeIntCon* intConstTree = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, 1); diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 7f704cd5672926..73a4863302581d 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -402,6 +402,32 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { +#if defined(TARGET_XARCH) + case NI_VectorT128_ConvertToDouble: + case NI_VectorT256_ConvertToDouble: + case NI_VectorT128_ConvertToInt64: + case NI_VectorT256_ConvertToInt64: + case NI_VectorT128_ConvertToUInt32: + case NI_VectorT256_ConvertToUInt32: + case NI_VectorT128_ConvertToUInt64: + case NI_VectorT256_ConvertToUInt64: + { + // TODO-XARCH-CQ: These intrinsics should be accelerated + return nullptr; + } + + case NI_VectorT128_ConvertToSingle: + case NI_VectorT256_ConvertToSingle: + { + if (simdBaseType == TYP_UINT) + { + // TODO-XARCH-CQ: These intrinsics should be accelerated + return nullptr; + } + break; + } +#endif // TARGET_XARCH + #if defined(TARGET_X86) case NI_VectorT128_CreateBroadcast: case NI_VectorT256_CreateBroadcast: @@ -676,9 +702,28 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdAbsNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } - case NI_VectorT128_Sum: + case NI_VectorT128_ConvertToInt32: + case NI_VectorT256_ConvertToInt32: { + assert(simdBaseType == TYP_FLOAT); + NamedIntrinsic convert = (simdSize == 32) ? NI_AVX_ConvertToVector256Int32WithTruncation + : NI_SSE2_ConvertToVector128Int32WithTruncation; + return gtNewSimdHWIntrinsicNode(retType, op1, convert, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_ConvertToSingle: + case NI_VectorT256_ConvertToSingle: + { + assert(simdBaseType == TYP_INT); + NamedIntrinsic convert = + (simdSize == 32) ? NI_AVX_ConvertToVector256Single : NI_SSE2_ConvertToVector128Single; + return gtNewSimdHWIntrinsicNode(retType, op1, convert, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + + case NI_VectorT128_Sum: + { GenTree* tmp; unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType); int haddCount = genLog2(vectorLength); @@ -753,6 +798,48 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdAbsNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } + case NI_VectorT128_ConvertToDouble: + { + assert((simdBaseType == TYP_LONG) || (simdBaseType == TYP_ULONG)); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToDouble, simdBaseJitType, + simdSize, /* isSimdAsHWIntrinsic */ true); + } + + case NI_VectorT128_ConvertToInt32: + { + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, + simdSize, /* isSimdAsHWIntrinsic */ true); + } + + case NI_VectorT128_ConvertToInt64: + { + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToInt64RoundToZero, + simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); + } + + case NI_VectorT128_ConvertToSingle: + { + assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + + case NI_VectorT128_ConvertToUInt32: + { + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, + simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); + } + + case NI_VectorT128_ConvertToUInt64: + { + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero, + simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_Sum: { GenTree* tmp; diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 2810a0e6ecfb1c..82cf2fb182766c 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -105,6 +105,12 @@ SIMD_AS_HWINTRINSIC_ID(VectorT128, AndNot, SIMD_AS_HWINTRINSIC_ID(VectorT128, As, 1, {NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Ceiling, NI_AdvSimd_Arm64_Ceiling}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, ConditionalSelect, 3, {NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToDouble, NI_VectorT128_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToSingle, NI_VectorT128_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT128, CreateBroadcast, ".ctor", 2, {NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(VectorT128, Dot, 2, {NI_Vector128_Dot, NI_Vector128_Dot, NI_Vector128_Dot, NI_Vector128_Dot, NI_Vector128_Dot, NI_Vector128_Dot, NI_Illegal, NI_Illegal, NI_Vector128_Dot, NI_Vector128_Dot}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, Equals, 2, {NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_Arm64_CompareEqual, NI_AdvSimd_Arm64_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_Arm64_CompareEqual}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 08cf5178282832..e3147ae9c129ab 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -105,6 +105,12 @@ SIMD_AS_HWINTRINSIC_ID(VectorT128, AndNot, SIMD_AS_HWINTRINSIC_ID(VectorT128, As, 1, {NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE41_Ceiling, NI_SSE41_Ceiling}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, ConditionalSelect, 3, {NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToDouble, NI_VectorT128_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToSingle, NI_VectorT128_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT128_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT128, CreateBroadcast, ".ctor", 2, {NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(VectorT128, Dot, 2, {NI_Illegal, NI_Illegal, NI_Vector128_Dot, NI_Vector128_Dot, NI_VectorT128_Dot, NI_VectorT128_Dot, NI_Illegal, NI_Illegal, NI_Vector128_Dot, NI_Vector128_Dot}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, Equals, 2, {NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_VectorT128_Equals, NI_VectorT128_Equals, NI_SSE_CompareEqual, NI_SSE2_CompareEqual}, SimdAsHWIntrinsicFlag::None) @@ -147,7 +153,13 @@ SIMD_AS_HWINTRINSIC_ID(VectorT256, AndNot, SIMD_AS_HWINTRINSIC_ID(VectorT256, As, 1, {NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT256, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Ceiling, NI_AVX_Ceiling}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT256, ConditionalSelect, 3, {NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_NM(VectorT256, CreateBroadcast, ".ctor", 2, {NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_ConvertToDouble, NI_VectorT256_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_ConvertToSingle, NI_VectorT256_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(VectorT256, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(VectorT256, Dot, 2, {NI_Illegal, NI_Illegal, NI_Vector256_Dot, NI_Vector256_Dot, NI_Vector256_Dot, NI_Vector256_Dot, NI_Illegal, NI_Illegal, NI_Vector256_Dot, NI_Vector256_Dot}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT256, Equals, 2, {NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX_CompareEqual, NI_AVX_CompareEqual}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT256, EqualsInstance, "Equals", 2, {NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality}, SimdAsHWIntrinsicFlag::InstanceMethod) diff --git a/src/coreclr/jit/simdcodegenxarch.cpp b/src/coreclr/jit/simdcodegenxarch.cpp index 9362aa05f521a4..5d364504cc0606 100644 --- a/src/coreclr/jit/simdcodegenxarch.cpp +++ b/src/coreclr/jit/simdcodegenxarch.cpp @@ -222,25 +222,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type result = INS_movaps; break; - case SIMDIntrinsicConvertToSingle: - result = INS_cvtdq2ps; - break; - - case SIMDIntrinsicConvertToDouble: - assert(baseType == TYP_LONG); - result = INS_cvtsi2sd; - break; - - case SIMDIntrinsicConvertToInt32: - assert(baseType == TYP_FLOAT); - result = INS_cvttps2dq; - break; - - case SIMDIntrinsicConvertToInt64: - assert(baseType == TYP_DOUBLE); - result = INS_cvttsd2si; - break; - case SIMDIntrinsicShiftLeftInternal: switch (baseType) { @@ -668,422 +649,6 @@ void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode) genProduceReg(simdNode); } -//---------------------------------------------------------------------------------- -// genSIMDIntrinsic32BitConvert: Generate code for 32-bit SIMD Convert (int/uint <-> float) -// -// Arguments: -// simdNode - The GT_SIMD node -// -// Return Value: -// None. -// -void CodeGen::genSIMDIntrinsic32BitConvert(GenTreeSIMD* simdNode) -{ - SIMDIntrinsicID intrinsicID = simdNode->GetSIMDIntrinsicId(); - assert((intrinsicID == SIMDIntrinsicConvertToSingle) || (intrinsicID == SIMDIntrinsicConvertToInt32)); - - GenTree* op1 = simdNode->Op(1); - var_types baseType = simdNode->GetSimdBaseType(); - regNumber targetReg = simdNode->GetRegNum(); - assert(targetReg != REG_NA); - var_types targetType = simdNode->TypeGet(); - - regNumber op1Reg = genConsumeReg(op1); - instruction ins = getOpForSIMDIntrinsic(simdNode->GetSIMDIntrinsicId(), baseType); - if (intrinsicID == SIMDIntrinsicConvertToSingle && baseType == TYP_UINT) - { - regNumber tmpIntReg = simdNode->GetSingleTempReg(RBM_ALLINT); - regNumber tmpReg = simdNode->ExtractTempReg(RBM_ALLFLOAT); - regNumber tmpReg2 = simdNode->GetSingleTempReg(RBM_ALLFLOAT); - assert(tmpReg != op1Reg && tmpReg2 != op1Reg); - - // We will generate the following: - // vmovdqu tmpReg2, op1Reg (copy the src and put it into tmpReg2) - // vmovdqu targetReg, op1Reg (copy the src and put it into targetReg) - // vpsrld targetReg, 16 (get upper 16 bits of src and put it into targetReg) - // vpslld tmpReg2, 16 - // vpsrld tmpReg2, 16 (get lower 16 bits of src and put it into tmpReg2) - // mov tmpIntReg, 0x5300000053000000 - // vmovd tmpReg, tmpIntReg - // vpbroadcastd tmpReg, tmpReg (build mask for converting upper 16 bits of src) - // vorps targetReg, tmpReg - // vsubps targetReg, tmpReg (convert upper 16 bits of src and put it into targetReg) - // vcvtdq2ps tmpReg2, tmpReg2 (convert lower 16 bits of src and put it into tmpReg2) - // vaddps targetReg, tmpReg2 (add upper 16 bits and lower 16 bits) - inst_Mov(targetType, tmpReg2, op1Reg, /* canSkip */ false); - inst_Mov(targetType, targetReg, op1Reg, /* canSkip */ true); - - // prepare upper 16 bits - GetEmitter()->emitIns_R_I(INS_psrld, emitActualTypeSize(targetType), targetReg, 16); - - // prepare lower 16 bits - GetEmitter()->emitIns_R_I(INS_pslld, emitActualTypeSize(targetType), tmpReg2, 16); - GetEmitter()->emitIns_R_I(INS_psrld, emitActualTypeSize(targetType), tmpReg2, 16); - -// prepare mask -#ifdef TARGET_AMD64 - GetEmitter()->emitIns_R_I(INS_mov, EA_8BYTE, tmpIntReg, (ssize_t)0X5300000053000000); - inst_Mov(targetType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_ULONG)); -#else - if (compiler->getSIMDSupportLevel() == SIMD_AVX2_Supported) - { - GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, tmpIntReg, (ssize_t)0X53000000); - inst_Mov(targetType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_UINT)); - } - else - { - GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, tmpIntReg, (ssize_t)0X00005300); - inst_RV_RV(INS_pxor, tmpReg, tmpReg, targetType, emitActualTypeSize(targetType)); - GetEmitter()->emitIns_R_R_I(INS_pinsrw, emitTypeSize(TYP_INT), tmpReg, tmpIntReg, 1); - GetEmitter()->emitIns_R_R_I(INS_pinsrw, emitTypeSize(TYP_INT), tmpReg, tmpIntReg, 3); - } -#endif - if (compiler->getSIMDSupportLevel() == SIMD_AVX2_Supported) - { - inst_RV_RV(INS_vpbroadcastd, tmpReg, tmpReg, targetType, emitActualTypeSize(targetType)); - } - else - { - inst_RV_RV(INS_movlhps, tmpReg, tmpReg, targetType, emitActualTypeSize(targetType)); - } - - // convert upper 16 bits - inst_RV_RV(INS_orps, targetReg, tmpReg, targetType, emitActualTypeSize(targetType)); - inst_RV_RV(INS_subps, targetReg, tmpReg, targetType, emitActualTypeSize(targetType)); - - // convert lower 16 bits - inst_RV_RV(ins, tmpReg2, tmpReg2, targetType, emitActualTypeSize(targetType)); - - // add lower 16 bits and upper 16 bits - inst_RV_RV(INS_addps, targetReg, tmpReg2, targetType, emitActualTypeSize(targetType)); - } - else - { - inst_RV_RV(ins, targetReg, op1Reg, targetType, emitActualTypeSize(targetType)); - } - genProduceReg(simdNode); -} - -//---------------------------------------------------------------------------------- -// genSIMDLo64BitConvert: Generate code to convert lower-most 64-bit item (long <--> double) -// -// Arguments: -// intrinsicID the SIMD intrinsic ID -// simdType the SIMD node type -// baseType the base type of value to be converted -// tmpReg the tmp reg -// tmpIntReg the tmp integer reg -// targetReg the target reg -// -// Return Value: -// None. -// -void CodeGen::genSIMDLo64BitConvert(SIMDIntrinsicID intrinsicID, - var_types simdType, - var_types baseType, - regNumber tmpReg, - regNumber tmpIntReg, - regNumber targetReg) -{ - instruction ins = getOpForSIMDIntrinsic(intrinsicID, baseType); - if (intrinsicID == SIMDIntrinsicConvertToDouble) - { - inst_Mov(TYP_LONG, tmpIntReg, tmpReg, /* canSkip */ false); - inst_RV_RV(ins, targetReg, tmpIntReg, baseType, emitActualTypeSize(baseType)); - } - else - { - inst_RV_RV(ins, tmpIntReg, tmpReg, baseType, emitActualTypeSize(baseType)); - inst_Mov(simdType, targetReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_LONG)); - } -} - -//---------------------------------------------------------------------------------- -// genSIMDIntrinsic64BitConvert: Generate code for 64-bit SIMD Convert (long/ulong <-> double) -// -// Arguments: -// simdNode - The GT_SIMD node -// -// Notes: -// There are no instructions for converting to/from 64-bit integers, so for these we -// do the conversion an element at a time. -// -void CodeGen::genSIMDIntrinsic64BitConvert(GenTreeSIMD* simdNode) -{ - SIMDIntrinsicID intrinsicID = simdNode->GetSIMDIntrinsicId(); - assert((intrinsicID == SIMDIntrinsicConvertToDouble) || (intrinsicID == SIMDIntrinsicConvertToInt64)); - - GenTree* op1 = simdNode->Op(1); - var_types baseType = simdNode->GetSimdBaseType(); - regNumber targetReg = simdNode->GetRegNum(); - assert(targetReg != REG_NA); - var_types simdType = simdNode->TypeGet(); - regNumber op1Reg = genConsumeReg(op1); - regNumber tmpIntReg = simdNode->GetSingleTempReg(RBM_ALLINT); - regNumber tmpReg; - regNumber tmpReg2; - regNumber tmpReg3; - SIMDLevel level = compiler->getSIMDSupportLevel(); - -#ifdef TARGET_X86 - if (baseType == TYP_LONG) - { - tmpReg = simdNode->ExtractTempReg(RBM_ALLFLOAT); - tmpReg2 = simdNode->ExtractTempReg(RBM_ALLFLOAT); - tmpReg3 = simdNode->GetSingleTempReg(RBM_ALLFLOAT); - assert(tmpReg != op1Reg && tmpReg2 != op1Reg && tmpReg3 != op1Reg); - } - else -#endif - if (level == SIMD_AVX2_Supported || (baseType == TYP_ULONG)) - { - tmpReg = simdNode->ExtractTempReg(RBM_ALLFLOAT); - tmpReg2 = simdNode->GetSingleTempReg(RBM_ALLFLOAT); - tmpReg3 = REG_NA; - assert(tmpReg != op1Reg && tmpReg2 != op1Reg); - } - else - { - tmpReg = simdNode->GetSingleTempReg(RBM_ALLFLOAT); - assert(tmpReg != op1Reg); - tmpReg2 = REG_NA; - tmpReg3 = REG_NA; - } - - if ((intrinsicID == SIMDIntrinsicConvertToDouble) && (baseType == TYP_ULONG)) - { - // We will generate the following - // vmovdqu tmpReg2, op1Reg (copy the src and put it into tmpReg2) - // vmovdqu targetReg, op1Reg (copy the src and put it into targetReg) - // vpsrlq targetReg, 32 (get upper 32 bits of src and put it into targetReg) - // vpsllq tmpReg2, 32 - // vpsrlq tmpReg2, 32 (get lower 32 bits of src and put it into tmpReg2) - // mov tmpIntReg, 0x4530000000000000 - // vmovd tmpReg, tmpIntReg - // vpbroadcastq tmpReg, tmpReg (build mask for upper 32 bits of src) - // vorpd targetReg, tmpReg - // vsubpd targetReg, tmpReg (convert upper 32 bits of src and put it into targetReg) - // mov tmpIntReg, 0x4330000000000000 - // vmovd tmpReg, tmpIntReg - // vpbroadcastq tmpReg, tmpReg (build mask for lower 32 bits of src) - // vorpd tmpReg2, tmpReg - // vsubpd tmpReg2, tmpReg (convert lower 32 bits of src and put it into tmpReg2) - // vaddpd targetReg, tmpReg2 (add upper 32 bits and lower 32 bits together) - inst_Mov(simdType, tmpReg2, op1Reg, /* canSkip */ false); - inst_Mov(simdType, targetReg, op1Reg, /* canSkip */ true); - - // prepare upper 32 bits - GetEmitter()->emitIns_R_I(INS_psrlq, emitActualTypeSize(simdType), targetReg, 32); - - // prepare lower 32 bits - GetEmitter()->emitIns_R_I(INS_psllq, emitActualTypeSize(simdType), tmpReg2, 32); - GetEmitter()->emitIns_R_I(INS_psrlq, emitActualTypeSize(simdType), tmpReg2, 32); - -// prepare mask for converting upper 32 bits -#ifdef TARGET_AMD64 - GetEmitter()->emitIns_R_I(INS_mov, EA_8BYTE, tmpIntReg, (ssize_t)0X4530000000000000); - inst_Mov(simdType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_ULONG)); -#else - GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, tmpIntReg, (ssize_t)0X45300000); - inst_Mov(simdType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_UINT)); - GetEmitter()->emitIns_R_I(INS_pslldq, EA_16BYTE, tmpReg, 4); -#endif - if (level == SIMD_AVX2_Supported) - { - inst_RV_RV(INS_vpbroadcastq, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - else - { - inst_RV_RV(INS_movlhps, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - - // convert upper 32 bits - inst_RV_RV(INS_orpd, targetReg, tmpReg, simdType, emitActualTypeSize(simdType)); - inst_RV_RV(INS_subpd, targetReg, tmpReg, simdType, emitActualTypeSize(simdType)); - -// prepare mask for converting lower 32 bits -#ifdef TARGET_AMD64 - GetEmitter()->emitIns_R_I(INS_mov, EA_8BYTE, tmpIntReg, (ssize_t)0X4330000000000000); - inst_Mov(simdType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_ULONG)); -#else - GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, tmpIntReg, (ssize_t)0X43300000); - inst_Mov(simdType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_UINT)); - GetEmitter()->emitIns_R_I(INS_pslldq, EA_16BYTE, tmpReg, 4); -#endif - if (level == SIMD_AVX2_Supported) - { - inst_RV_RV(INS_vpbroadcastq, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - else - { - inst_RV_RV(INS_movlhps, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - - // convert lower 32 bits - inst_RV_RV(INS_orpd, tmpReg2, tmpReg, simdType, emitActualTypeSize(simdType)); - inst_RV_RV(INS_subpd, tmpReg2, tmpReg, simdType, emitActualTypeSize(simdType)); - - // add lower 32 bits and upper 32 bits - inst_RV_RV(INS_addpd, targetReg, tmpReg2, simdType, emitActualTypeSize(simdType)); - } - else if ((intrinsicID == SIMDIntrinsicConvertToDouble) && (baseType == TYP_LONG)) - { -#ifdef TARGET_AMD64 - instruction rightShiftIns = getOpForSIMDIntrinsic(SIMDIntrinsicShiftRightInternal, TYP_SIMD16); - instruction leftShiftIns = getOpForSIMDIntrinsic(SIMDIntrinsicShiftLeftInternal, TYP_SIMD16); - - if (level == SIMD_AVX2_Supported) - { - // Extract the high 16-bits - GetEmitter()->emitIns_R_R_I(INS_vextracti128, EA_32BYTE, tmpReg, op1Reg, 0x01); - - // Put v[3] (the high-order element) in tmpReg2 and convert it. - inst_Mov(simdType, tmpReg2, tmpReg, /* canSkip */ false); - GetEmitter()->emitIns_R_I(rightShiftIns, emitActualTypeSize(simdType), tmpReg2, 8); - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, tmpReg2, tmpIntReg, tmpReg2); - - // Shift the resulting 64-bits left. - GetEmitter()->emitIns_R_I(leftShiftIns, emitActualTypeSize(simdType), tmpReg2, 8); - - // Convert v[2], in the lo bits of tmpReg. - // For the convert to double, the convert preserves the upper bits in tmpReg2. - // For the integer convert, we have to put it in tmpReg and or it in, since movd clears the upper bits. - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, tmpReg, tmpIntReg, tmpReg2); - } - - // Put v[1] in tmpReg. - inst_Mov(simdType, tmpReg, op1Reg, /* canSkip */ false); - GetEmitter()->emitIns_R_I(rightShiftIns, emitActualTypeSize(simdType), tmpReg, 8); - - // At this point we have v[1] in the low-order 64-bits of tmpReg. Convert it. - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, tmpReg, tmpIntReg, tmpReg); - - // Shift the resulting 64-bits left. - GetEmitter()->emitIns_R_I(leftShiftIns, emitActualTypeSize(simdType), tmpReg, 8); - - // Convert the lo 64-bits into targetReg - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, op1Reg, tmpIntReg, tmpReg); - - // Merge or copy the results (only at this point are we done with op1Reg). - inst_Mov(simdType, targetReg, tmpReg, /* canSkip */ true); - - if (level == SIMD_AVX2_Supported) - { - GetEmitter()->emitIns_R_R_I(INS_vinsertf128, EA_32BYTE, targetReg, tmpReg2, 0x01); - } -#else - // get the sign bit and put it in tmpReg3 - inst_Mov(simdType, tmpReg3, op1Reg, /* canSkip */ false); - GetEmitter()->emitIns_R_I(INS_psrlq, emitActualTypeSize(simdType), tmpReg3, 63); - GetEmitter()->emitIns_R_I(INS_psllq, emitActualTypeSize(simdType), tmpReg3, 63); - - // get the absolute value of src and put it into tmpReg2 and targetReg - inst_Mov(simdType, tmpReg2, op1Reg, /* canSkip */ false); - GetEmitter()->emitIns_R_R_I(INS_pshufd, emitActualTypeSize(simdType), tmpReg, op1Reg, (int8_t)SHUFFLE_WWYY); - GetEmitter()->emitIns_R_I(INS_psrad, emitActualTypeSize(simdType), tmpReg, 32); - inst_RV_RV(INS_pxor, tmpReg2, tmpReg, baseType, emitActualTypeSize(simdType)); - inst_RV_RV(INS_psubq, tmpReg2, tmpReg, baseType, emitActualTypeSize(simdType)); - inst_Mov(simdType, targetReg, tmpReg2, /* canSkip */ false); - - // prepare upper 32 bits - GetEmitter()->emitIns_R_I(INS_psrlq, emitActualTypeSize(simdType), targetReg, 32); - - // prepare lower 32 bits - GetEmitter()->emitIns_R_I(INS_psllq, emitActualTypeSize(simdType), tmpReg2, 32); - GetEmitter()->emitIns_R_I(INS_psrlq, emitActualTypeSize(simdType), tmpReg2, 32); - - // prepare mask for converting upper 32 bits - GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, tmpIntReg, (ssize_t)0X45300000); - inst_Mov(simdType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_UINT)); - GetEmitter()->emitIns_R_I(INS_pslldq, EA_16BYTE, tmpReg, 4); - - if (level == SIMD_AVX2_Supported) - { - inst_RV_RV(INS_vpbroadcastq, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - else - { - inst_RV_RV(INS_movlhps, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - - // convert upper 32 bits - inst_RV_RV(INS_orpd, targetReg, tmpReg, simdType, emitActualTypeSize(simdType)); - inst_RV_RV(INS_subpd, targetReg, tmpReg, simdType, emitActualTypeSize(simdType)); - - // prepare mask for converting lower 32 bits - GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, tmpIntReg, (ssize_t)0X43300000); - inst_Mov(simdType, tmpReg, tmpIntReg, /* canSkip */ false, emitActualTypeSize(TYP_UINT)); - GetEmitter()->emitIns_R_I(INS_pslldq, EA_16BYTE, tmpReg, 4); - - if (level == SIMD_AVX2_Supported) - { - inst_RV_RV(INS_vpbroadcastq, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - else - { - inst_RV_RV(INS_movlhps, tmpReg, tmpReg, simdType, emitActualTypeSize(simdType)); - } - - // convert lower 32 bits - inst_RV_RV(INS_orpd, tmpReg2, tmpReg, simdType, emitActualTypeSize(simdType)); - inst_RV_RV(INS_subpd, tmpReg2, tmpReg, simdType, emitActualTypeSize(simdType)); - - // add lower 32 bits and upper 32 bits - inst_RV_RV(INS_addpd, targetReg, tmpReg2, simdType, emitActualTypeSize(simdType)); - - // add sign bit - inst_RV_RV(INS_por, targetReg, tmpReg3, simdType, emitActualTypeSize(simdType)); -#endif - } - else - { - instruction rightShiftIns = getOpForSIMDIntrinsic(SIMDIntrinsicShiftRightInternal, TYP_SIMD16); - instruction leftShiftIns = getOpForSIMDIntrinsic(SIMDIntrinsicShiftLeftInternal, TYP_SIMD16); - - if (level == SIMD_AVX2_Supported) - { - // Extract the high 16-bits - GetEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg, op1Reg, 0x01); - - // Put v[3] (the high-order element) in tmpReg2 and convert it. - inst_Mov(simdType, tmpReg2, tmpReg, /* canSkip */ false); - GetEmitter()->emitIns_R_I(rightShiftIns, emitActualTypeSize(simdType), tmpReg2, 8); - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, tmpReg2, tmpIntReg, tmpReg2); - - // Shift the resulting 64-bits left. - GetEmitter()->emitIns_R_I(leftShiftIns, emitActualTypeSize(simdType), tmpReg2, 8); - - // Convert v[2], in the lo bits of tmpReg. - // For the convert to double, the convert preserves the upper bits in tmpReg2. - // For the integer convert, we have to put it in tmpReg and or it in, since movd clears the upper bits. - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, tmpReg, tmpIntReg, tmpReg); - inst_RV_RV(INS_por, tmpReg2, tmpReg, simdType, emitActualTypeSize(simdType)); - } - - // Put v[1] in tmpReg. - inst_Mov(simdType, tmpReg, op1Reg, /* canSkip */ false); - GetEmitter()->emitIns_R_I(rightShiftIns, emitActualTypeSize(simdType), tmpReg, 8); - - // At this point we have v[1] in the low-order 64-bits of tmpReg. Convert it. - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, tmpReg, tmpIntReg, tmpReg); - - // Shift the resulting 64-bits left. - GetEmitter()->emitIns_R_I(leftShiftIns, emitActualTypeSize(simdType), tmpReg, 8); - - // Convert the lo 64-bits into targetReg - genSIMDLo64BitConvert(intrinsicID, simdType, baseType, op1Reg, tmpIntReg, targetReg); - - // Merge or copy the results (only at this point are we done with op1Reg). - assert(tmpReg != targetReg); - inst_RV_RV(INS_por, targetReg, tmpReg, simdType, emitActualTypeSize(simdType)); - if (level == SIMD_AVX2_Supported) - { - GetEmitter()->emitIns_R_R_I(INS_vinserti128, EA_32BYTE, targetReg, tmpReg2, 0x01); - } - } - genProduceReg(simdNode); -} - //-------------------------------------------------------------------------------- // genSIMDExtractUpperHalf: Generate code to extract the upper half of a SIMD register // @@ -1625,16 +1190,6 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) genSIMDIntrinsicUnOp(simdNode); break; - case SIMDIntrinsicConvertToSingle: - case SIMDIntrinsicConvertToInt32: - genSIMDIntrinsic32BitConvert(simdNode); - break; - - case SIMDIntrinsicConvertToDouble: - case SIMDIntrinsicConvertToInt64: - genSIMDIntrinsic64BitConvert(simdNode); - break; - case SIMDIntrinsicSub: case SIMDIntrinsicBitwiseAnd: case SIMDIntrinsicBitwiseOr: diff --git a/src/coreclr/jit/simdintrinsiclist.h b/src/coreclr/jit/simdintrinsiclist.h index 0b354b533702c3..bb48b01e7f059b 100644 --- a/src/coreclr/jit/simdintrinsiclist.h +++ b/src/coreclr/jit/simdintrinsiclist.h @@ -70,15 +70,6 @@ SIMD_INTRINSIC("op_BitwiseOr", false, BitwiseOr, // Cast SIMD_INTRINSIC("op_Explicit", false, Cast, "Cast", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -// Convert int/uint to single -SIMD_INTRINSIC("ConvertToSingle", false, ConvertToSingle, "ConvertToSingle", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_UINT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) -// Convert long/ulong to double -SIMD_INTRINSIC("ConvertToDouble", false, ConvertToDouble, "ConvertToDouble", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_LONG, TYP_ULONG, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) -// Convert single to int -SIMD_INTRINSIC("ConvertToInt32", false, ConvertToInt32, "ConvertToInt32", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) -// Convert double to long -SIMD_INTRINSIC("ConvertToInt64", false, ConvertToInt64, "ConvertToInt64", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) - // Miscellaneous SIMD_INTRINSIC("get_IsHardwareAccelerated", false, HWAccel, "HWAccel", TYP_BOOL, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoArmIntrinsics.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoArmIntrinsics.xml index d30ea62e250f4f..1da6f6d57d26e3 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoArmIntrinsics.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoArmIntrinsics.xml @@ -1,52 +1,55 @@ + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml index 59d0783d0a7895..50dababbb347c4 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xml @@ -1,5 +1,8 @@ + + + diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 70c36a619ec635..86ad06f841e37d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; using Internal.Runtime.CompilerServices; @@ -311,17 +312,19 @@ public static Vector ConditionalSelect(Vector condition, VectorThe vector to convert. /// The converted vector. [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector ConvertToDouble(Vector value) { - Unsafe.SkipInit(out Vector result); - - for (int i = 0; i < Vector.Count; i++) + if (Avx2.IsSupported) { - var element = (double)value.GetElementUnsafe(i); - result.SetElementUnsafe(i, element); + Debug.Assert(Vector.Count == Vector256.Count); + return Vector256.ConvertToDouble(value.AsVector256()).AsVector(); + } + else + { + Debug.Assert(Vector.Count == Vector128.Count); + return Vector128.ConvertToDouble(value.AsVector128()).AsVector(); } - - return result; } /// Converts a to a . @@ -329,17 +332,19 @@ public static unsafe Vector ConvertToDouble(Vector value) /// The converted vector. [CLSCompliant(false)] [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector ConvertToDouble(Vector value) { - Unsafe.SkipInit(out Vector result); - - for (int i = 0; i < Vector.Count; i++) + if (Avx2.IsSupported) { - var element = (double)value.GetElementUnsafe(i); - result.SetElementUnsafe(i, element); + Debug.Assert(Vector.Count == Vector256.Count); + return Vector256.ConvertToDouble(value.AsVector256()).AsVector(); + } + else + { + Debug.Assert(Vector.Count == Vector128.Count); + return Vector128.ConvertToDouble(value.AsVector128()).AsVector(); } - - return result; } /// Converts a to a . @@ -398,17 +403,19 @@ public static unsafe Vector ConvertToSingle(Vector value) /// The converted vector. [CLSCompliant(false)] [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector ConvertToSingle(Vector value) { - Unsafe.SkipInit(out Vector result); - - for (int i = 0; i < Vector.Count; i++) + if (Avx2.IsSupported) { - var element = (float)value.GetElementUnsafe(i); - result.SetElementUnsafe(i, element); + Debug.Assert(Vector.Count == Vector256.Count); + return Vector256.ConvertToSingle(value.AsVector256()).AsVector(); + } + else + { + Debug.Assert(Vector.Count == Vector128.Count); + return Vector128.ConvertToSingle(value.AsVector128()).AsVector(); } - - return result; } /// Converts a to a . diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 445a0af111baa9..57e7d3f5026bde 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -359,17 +359,50 @@ public static Vector128 ConditionalSelect(Vector128 condition, Vector12 /// The vector to convert. /// The converted vector. [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector128 ConvertToDouble(Vector128 vector) { - Unsafe.SkipInit(out Vector128 result); + if (Sse2.IsSupported) + { + // Based on __m256d int64_to_double_fast_precise(const __m256i v) + // from https://stackoverflow.com/a/41223013/12860347. CC BY-SA 4.0 - for (int i = 0; i < Vector128.Count; i++) + Vector128 lowerBits; + + if (Avx2.IsSupported) + { + lowerBits = vector.AsInt32(); + lowerBits = Avx2.Blend(lowerBits, Create(0x43300000_00000000).AsInt32(), 0b1010); // Blend the 32 lowest significant bits of vector with the bit representation of double(2^52) + } + else + { + lowerBits = Sse2.And(vector, Create(0x00000000_FFFFFFFFL)).AsInt32(); + lowerBits = Sse2.Or(lowerBits, Create(0x43300000_00000000).AsInt32()); + } + + var upperBits = Sse2.ShiftRightLogical(vector, 32); // Extract the 32 most significant bits of vector + upperBits = Sse2.Xor(upperBits, Create(0x45300000_80000000)); // Flip the msb of upperBits and blend with the bit representation of double(2^84 + 2^63) + + var result = Sse2.Subtract(upperBits.AsDouble(), Create(0x45300000_80100000).AsDouble()); // Compute in double precision: (upper - (2^84 + 2^63 + 2^52)) + lower + return Sse2.Add(result, lowerBits.AsDouble()); + } + else { - var value = (double)vector.GetElementUnsafe(i); - result.SetElementUnsafe(i, value); + return SoftwareFallback(vector); } - return result; + static Vector128 SoftwareFallback(Vector128 vector) + { + Unsafe.SkipInit(out Vector128 result); + + for (int i = 0; i < Vector128.Count; i++) + { + var value = (double)vector.GetElementUnsafe(i); + result.SetElementUnsafe(i, value); + } + + return result; + } } /// Converts a to a . @@ -377,17 +410,50 @@ public static unsafe Vector128 ConvertToDouble(Vector128 vector) /// The converted vector. [CLSCompliant(false)] [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector128 ConvertToDouble(Vector128 vector) { - Unsafe.SkipInit(out Vector128 result); + if (Sse2.IsSupported) + { + // Based on __m256d uint64_to_double_fast_precise(const __m256i v) + // from https://stackoverflow.com/a/41223013/12860347. CC BY-SA 4.0 - for (int i = 0; i < Vector128.Count; i++) + Vector128 lowerBits; + + if (Avx2.IsSupported) + { + lowerBits = vector.AsUInt32(); + lowerBits = Avx2.Blend(lowerBits, Create(0x43300000_00000000UL).AsUInt32(), 0b1010); // Blend the 32 lowest significant bits of vector with the bit representation of double(2^52) + } + else + { + lowerBits = Sse2.And(vector, Create(0x00000000_FFFFFFFFUL)).AsUInt32(); + lowerBits = Sse2.Or(lowerBits, Create(0x43300000_00000000UL).AsUInt32()); + } + + var upperBits = Sse2.ShiftRightLogical(vector, 32); // Extract the 32 most significant bits of vector + upperBits = Sse2.Xor(upperBits, Create(0x45300000_00000000UL)); // Blend upperBits with the bit representation of double(2^84) + + var result = Sse2.Subtract(upperBits.AsDouble(), Create(0x45300000_00100000UL).AsDouble()); // Compute in double precision: (upper - (2^84 + 2^52)) + lower + return Sse2.Add(result, lowerBits.AsDouble()); + } + else { - var value = (double)vector.GetElementUnsafe(i); - result.SetElementUnsafe(i, value); + return SoftwareFallback(vector); } - return result; + static Vector128 SoftwareFallback(Vector128 vector) + { + Unsafe.SkipInit(out Vector128 result); + + for (int i = 0; i < Vector128.Count; i++) + { + var value = (double)vector.GetElementUnsafe(i); + result.SetElementUnsafe(i, value); + } + + return result; + } } /// Converts a to a . @@ -446,17 +512,56 @@ public static unsafe Vector128 ConvertToSingle(Vector128 vector) /// The converted vector. [CLSCompliant(false)] [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector128 ConvertToSingle(Vector128 vector) { - Unsafe.SkipInit(out Vector128 result); + if (Sse2.IsSupported) + { + // This first bit of magic works because float can exactly represent integers up to 2^24 + // + // This means everything between 0 and 2^16 (ushort.MaxValue + 1) are exact and so + // converting each of the upper and lower halves will give an exact result - for (int i = 0; i < Vector128.Count; i++) + var lowerBits = Sse2.And(vector, Create(0x0000FFFFU)).AsInt32(); + var upperBits = Sse2.ShiftRightLogical(vector, 16).AsInt32(); + + var lower = Sse2.ConvertToVector128Single(lowerBits); + var upper = Sse2.ConvertToVector128Single(upperBits); + + // This next bit of magic works because all multiples of 65536, at least up to 65535 + // are likewise exactly representable + // + // This means that scaling upper by 65536 gives us the exactly representable base value + // and then the remaining lower value, which is likewise up to 65535 can be added on + // giving us a result that will correctly round to the nearest representable value + + if (Fma.IsSupported) + { + return Fma.MultiplyAdd(upper, Vector128.Create(65536.0f), lower); + } + else + { + var result = Sse.Multiply(upper, Vector128.Create(65536.0f)); + return Sse.Add(result, lower); + } + } + else { - var value = (float)vector.GetElementUnsafe(i); - result.SetElementUnsafe(i, value); + return SoftwareFallback(vector); } - return result; + static Vector128 SoftwareFallback(Vector128 vector) + { + Unsafe.SkipInit(out Vector128 result); + + for (int i = 0; i < Vector128.Count; i++) + { + var value = (float)vector.GetElementUnsafe(i); + result.SetElementUnsafe(i, value); + } + + return result; + } } /// Converts a to a . diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index d696075b9c9720..9c0b14683ab2b9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -320,17 +320,42 @@ public static Vector256 ConditionalSelect(Vector256 condition, Vector25 /// The vector to convert. /// The converted vector. [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector256 ConvertToDouble(Vector256 vector) { - Unsafe.SkipInit(out Vector256 result); + if (Avx2.IsSupported) + { + // Based on __m256d int64_to_double_fast_precise(const __m256i v) + // from https://stackoverflow.com/a/41223013/12860347. CC BY-SA 4.0 - for (int i = 0; i < Vector256.Count; i++) + Vector256 lowerBits; + + lowerBits = vector.AsInt32(); + lowerBits = Avx2.Blend(lowerBits, Create(0x43300000_00000000).AsInt32(), 0b10101010); // Blend the 32 lowest significant bits of vector with the bit representation of double(2^52) + + var upperBits = Avx2.ShiftRightLogical(vector, 32); // Extract the 32 most significant bits of vector + upperBits = Avx2.Xor(upperBits, Create(0x45300000_80000000)); // Flip the msb of upperBits and blend with the bit representation of double(2^84 + 2^63) + + var result = Avx.Subtract(upperBits.AsDouble(), Create(0x45300000_80100000).AsDouble()); // Compute in double precision: (upper - (2^84 + 2^63 + 2^52)) + lower + return Avx.Add(result, lowerBits.AsDouble()); + } + else { - var value = (double)vector.GetElementUnsafe(i); - result.SetElementUnsafe(i, value); + return SoftwareFallback(vector); } - return result; + static Vector256 SoftwareFallback(Vector256 vector) + { + Unsafe.SkipInit(out Vector256 result); + + for (int i = 0; i < Vector256.Count; i++) + { + var value = (double)vector.GetElementUnsafe(i); + result.SetElementUnsafe(i, value); + } + + return result; + } } /// Converts a to a . @@ -338,17 +363,42 @@ public static unsafe Vector256 ConvertToDouble(Vector256 vector) /// The converted vector. [CLSCompliant(false)] [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector256 ConvertToDouble(Vector256 vector) { - Unsafe.SkipInit(out Vector256 result); + if (Avx2.IsSupported) + { + // Based on __m256d uint64_to_double_fast_precise(const __m256i v) + // from https://stackoverflow.com/a/41223013/12860347. CC BY-SA 4.0 - for (int i = 0; i < Vector256.Count; i++) + Vector256 lowerBits; + + lowerBits = vector.AsUInt32(); + lowerBits = Avx2.Blend(lowerBits, Create(0x43300000_00000000UL).AsUInt32(), 0b10101010); // Blend the 32 lowest significant bits of vector with the bit representation of double(2^52) */ + + var upperBits = Avx2.ShiftRightLogical(vector, 32); // Extract the 32 most significant bits of vector + upperBits = Avx2.Xor(upperBits, Create(0x45300000_00000000UL)); // Blend upperBits with the bit representation of double(2^84) + + var result = Avx.Subtract(upperBits.AsDouble(), Create(0x45300000_00100000UL).AsDouble()); // Compute in double precision: (upper - (2^84 + 2^52)) + lower + return Avx.Add(result, lowerBits.AsDouble()); + } + else { - var value = (double)vector.GetElementUnsafe(i); - result.SetElementUnsafe(i, value); + return SoftwareFallback(vector); } - return result; + static Vector256 SoftwareFallback(Vector256 vector) + { + Unsafe.SkipInit(out Vector256 result); + + for (int i = 0; i < Vector256.Count; i++) + { + var value = (double)vector.GetElementUnsafe(i); + result.SetElementUnsafe(i, value); + } + + return result; + } } /// Converts a to a . @@ -407,17 +457,56 @@ public static unsafe Vector256 ConvertToSingle(Vector256 vector) /// The converted vector. [CLSCompliant(false)] [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Vector256 ConvertToSingle(Vector256 vector) { - Unsafe.SkipInit(out Vector256 result); + if (Avx2.IsSupported) + { + // This first bit of magic works because float can exactly represent integers up to 2^24 + // + // This means everything between 0 and 2^16 (ushort.MaxValue + 1) are exact and so + // converting each of the upper and lower halves will give an exact result - for (int i = 0; i < Vector256.Count; i++) + var lowerBits = Avx2.And(vector, Create(0x0000FFFFU)).AsInt32(); + var upperBits = Avx2.ShiftRightLogical(vector, 16).AsInt32(); + + var lower = Avx.ConvertToVector256Single(lowerBits); + var upper = Avx.ConvertToVector256Single(upperBits); + + // This next bit of magic works because all multiples of 65536, at least up to 65535 + // are likewise exactly representable + // + // This means that scaling upper by 65536 gives us the exactly representable base value + // and then the remaining lower value, which is likewise up to 65535 can be added on + // giving us a result that will correctly round to the nearest representable value + + if (Fma.IsSupported) + { + return Fma.MultiplyAdd(upper, Vector256.Create(65536.0f), lower); + } + else + { + var result = Avx.Multiply(upper, Vector256.Create(65536.0f)); + return Avx.Add(result, lower); + } + } + else { - var value = (float)vector.GetElementUnsafe(i); - result.SetElementUnsafe(i, value); + return SoftwareFallback(vector); } - return result; + static Vector256 SoftwareFallback(Vector256 vector) + { + Unsafe.SkipInit(out Vector256 result); + + for (int i = 0; i < Vector256.Count; i++) + { + var value = (float)vector.GetElementUnsafe(i); + result.SetElementUnsafe(i, value); + } + + return result; + } } /// Converts a to a . diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/GenerateTests.csx b/src/tests/JIT/HardwareIntrinsics/General/Shared/GenerateTests.csx index 04e1cf8b2ee9ab..84df601afdf6a7 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/GenerateTests.csx +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/GenerateTests.csx @@ -89,14 +89,14 @@ private static readonly (string templateFileName, Dictionary tem ("VectorTernaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (uint)((secondOp[0] & firstOp[0]) | (thirdOp[0] & ~firstOp[0]))", ["ValidateRemainingResults"] = "result[i] != (uint)((secondOp[i] & firstOp[i]) | (thirdOp[i] & ~firstOp[i]))" }), ("VectorTernaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != (ulong)((secondOp[0] & firstOp[0]) | (thirdOp[0] & ~firstOp[0]))", ["ValidateRemainingResults"] = "result[i] != (ulong)((secondOp[i] & firstOp[i]) | (thirdOp[i] & ~firstOp[i]))" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToInt32", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (int)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (int)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToInt64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToUInt32", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (uint)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToUInt64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (ulong)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (ulong)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64())", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToInt32", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (int)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (int)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToInt64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToUInt32", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (uint)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "ConvertToUInt64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (ulong)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (ulong)(firstOp[i])" }), ("VectorCreateTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "Create", ["VectorType"] = "Vector64", ["BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "resultElements[0] != expectedValue", ["ValidateRemainingResults"] = "resultElements[i] != expectedValue" }), ("VectorCreateTest.template", new Dictionary { ["Isa"] = "Vector64", ["Method"] = "Create", ["VectorType"] = "Vector64", ["BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "resultElements[0] != expectedValue", ["ValidateRemainingResults"] = "resultElements[i] != expectedValue" }), @@ -719,14 +719,14 @@ private static readonly (string templateFileName, Dictionary tem ("VectorTernaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (uint)((secondOp[0] & firstOp[0]) | (thirdOp[0] & ~firstOp[0]))", ["ValidateRemainingResults"] = "result[i] != (uint)((secondOp[i] & firstOp[i]) | (thirdOp[i] & ~firstOp[i]))" }), ("VectorTernaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != (ulong)((secondOp[0] & firstOp[0]) | (thirdOp[0] & ~firstOp[0]))", ["ValidateRemainingResults"] = "result[i] != (ulong)((secondOp[i] & firstOp[i]) | (thirdOp[i] & ~firstOp[i]))" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToInt32", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (int)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (int)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToInt64", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToUInt32", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (uint)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToUInt64", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (ulong)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (ulong)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64())", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToInt32", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (int)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (int)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToInt64", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToUInt32", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (uint)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "ConvertToUInt64", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (ulong)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (ulong)(firstOp[i])" }), ("VectorCreateTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "Create", ["VectorType"] = "Vector128", ["BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "resultElements[0] != expectedValue", ["ValidateRemainingResults"] = "resultElements[i] != expectedValue" }), ("VectorCreateTest.template", new Dictionary { ["Isa"] = "Vector128", ["Method"] = "Create", ["VectorType"] = "Vector128", ["BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "resultElements[0] != expectedValue", ["ValidateRemainingResults"] = "resultElements[i] != expectedValue" }), @@ -1402,14 +1402,14 @@ private static readonly (string templateFileName, Dictionary tem ("VectorTernaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (uint)((secondOp[0] & firstOp[0]) | (thirdOp[0] & ~firstOp[0]))", ["ValidateRemainingResults"] = "result[i] != (uint)((secondOp[i] & firstOp[i]) | (thirdOp[i] & ~firstOp[i]))" }), ("VectorTernaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != (ulong)((secondOp[0] & firstOp[0]) | (thirdOp[0] & ~firstOp[0]))", ["ValidateRemainingResults"] = "result[i] != (ulong)((secondOp[i] & firstOp[i]) | (thirdOp[i] & ~firstOp[i]))" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToInt32", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (int)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (int)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToInt64", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToUInt32", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (uint)(firstOp[i])" }), - ("VectorUnaryOpTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToUInt64", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (ulong)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (ulong)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToDouble", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64())", ["ValidateFirstResult"] = "result[0] != (double)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (double)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToInt32", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (int)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (int)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToInt64", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToSingle", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (float)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (float)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToUInt32", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (uint)(firstOp[i])" }), + ("VectorConvertToTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "ConvertToUInt64", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (ulong)(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (ulong)(firstOp[i])" }), ("VectorCreateTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "Create", ["VectorType"] = "Vector256", ["BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "resultElements[0] != expectedValue", ["ValidateRemainingResults"] = "resultElements[i] != expectedValue" }), ("VectorCreateTest.template", new Dictionary { ["Isa"] = "Vector256", ["Method"] = "Create", ["VectorType"] = "Vector256", ["BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "resultElements[0] != expectedValue", ["ValidateRemainingResults"] = "resultElements[i] != expectedValue" }), @@ -2489,7 +2489,7 @@ private static void ProcessInput(StreamWriter testListFile, string groupName, (s testName = $"{input.templateData["Method"]}.{input.templateData["BaseType"]}"; testListFile.WriteLine($@" [""{testName}""] = {input.templateData["Method"]}{input.templateData["BaseType"]},"); } - else if (input.templateFileName == "VectorNarrowTest.template") + else if ((input.templateFileName == "VectorNarrowTest.template") || (input.templateFileName == "VectorConvertToTest.template")) { testName = $"{input.templateData["Method"]}.{input.templateData["Op1BaseType"]}"; testListFile.WriteLine($@" [""{testName}""] = {input.templateData["Method"]}{input.templateData["Op1BaseType"]},"); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorConvertToTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorConvertToTest.template new file mode 100644 index 00000000000000..ebb0731ab936bf --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorConvertToTest.template @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void {Method}{Op1BaseType}() + { + var test = new VectorUnaryOpTest__{Method}{Op1BaseType}(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__{Method}{Op1BaseType} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__{Method}{Op1BaseType} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private static {Op1VectorType}<{Op1BaseType}> _clsVar1; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__{Method}{Op1BaseType}() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _clsVar1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + } + + public VectorUnaryOpTest__{Method}{Op1BaseType}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { + typeof({Op1VectorType}<{Op1BaseType}>) + }); + + if (method is null) + { + method = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), 1, new Type[] { + typeof({Op1VectorType}<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof({RetBaseType})); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = {Isa}.{Method}( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__{Method}{Op1BaseType}(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if ({ValidateFirstResult}) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults}) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.Int64.cs new file mode 100644 index 00000000000000..118a2562590064 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.Int64.cs @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void ConvertToDoubleInt64() + { + var test = new VectorUnaryOpTest__ConvertToDoubleInt64(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Double[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleInt64 testClass) + { + var result = Vector128.ConvertToDouble(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__ConvertToDoubleInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public VectorUnaryOpTest__ConvertToDoubleInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Vector128.ConvertToDouble( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof(Vector128).GetMethod(nameof(Vector128.ConvertToDouble), new Type[] { + typeof(Vector128) + }); + + if (method is null) + { + method = typeof(Vector128).GetMethod(nameof(Vector128.ConvertToDouble), 1, new Type[] { + typeof(Vector128<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof(Double)); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Vector128.ConvertToDouble( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = Vector128.ConvertToDouble(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__ConvertToDoubleInt64(); + var result = Vector128.ConvertToDouble(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Vector128.ConvertToDouble(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Vector128.ConvertToDouble(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != (double)(firstOp[0])) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != (double)(firstOp[i])) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Vector128)}.{nameof(Vector128.ConvertToDouble)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.Double.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.UInt64.cs similarity index 94% rename from src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.Double.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.UInt64.cs index 145513db669d52..df5518208f5aaa 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.Double.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToDouble.UInt64.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToDoubleDouble() + private static void ConvertToDoubleUInt64() { - var test = new VectorUnaryOpTest__ConvertToDoubleDouble(); + var test = new VectorUnaryOpTest__ConvertToDoubleUInt64(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToDoubleDouble() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleDouble + public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleUInt64 { private struct DataTable { @@ -107,13 +107,13 @@ public static TestStruct Create() { var testStruct = new TestStruct(); - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleDouble testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleUInt64 testClass) { var result = Vector128.ConvertToDouble(_fld1); @@ -135,20 +135,20 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleDouble testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToDoubleDouble() + static VectorUnaryOpTest__ConvertToDoubleUInt64() { - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToDoubleDouble() + public VectorUnaryOpTest__ConvertToDoubleUInt64() { Succeeded = true; - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); } @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToDoubleDouble(); + var test = new VectorUnaryOpTest__ConvertToDoubleUInt64(); var result = Vector128.ConvertToDouble(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt32.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt32.Single.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt32.Int32.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt32.Single.cs index efcd0171107c1b..d80b9246cac5bf 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt32.Int32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt32.Single.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToInt32Int32() + private static void ConvertToInt32Single() { - var test = new VectorUnaryOpTest__ConvertToInt32Int32(); + var test = new VectorUnaryOpTest__ConvertToInt32Single(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToInt32Int32() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToInt32Int32 + public sealed unsafe class VectorUnaryOpTest__ConvertToInt32Single { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Int32 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Single testClass) { var result = Vector128.ConvertToInt32(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Int32 testClas private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToInt32Int32() + static VectorUnaryOpTest__ConvertToInt32Single() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToInt32Int32() + public VectorUnaryOpTest__ConvertToInt32Single() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToInt32Int32(); + var test = new VectorUnaryOpTest__ConvertToInt32Single(); var result = Vector128.ConvertToInt32(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt64.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt64.Double.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt64.Int64.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt64.Double.cs index e8cae40603daac..f3fc95fc84062d 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt64.Int64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToInt64.Double.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToInt64Int64() + private static void ConvertToInt64Double() { - var test = new VectorUnaryOpTest__ConvertToInt64Int64(); + var test = new VectorUnaryOpTest__ConvertToInt64Double(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToInt64Int64() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToInt64Int64 + public sealed unsafe class VectorUnaryOpTest__ConvertToInt64Double { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Int64 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Double testClass) { var result = Vector128.ConvertToInt64(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Int64 testClas private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToInt64Int64() + static VectorUnaryOpTest__ConvertToInt64Double() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToInt64Int64() + public VectorUnaryOpTest__ConvertToInt64Double() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToInt64Int64(); + var test = new VectorUnaryOpTest__ConvertToInt64Double(); var result = Vector128.ConvertToInt64(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.Int32.cs new file mode 100644 index 00000000000000..0fe365a8c42f30 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.Int32.cs @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void ConvertToSingleInt32() + { + var test = new VectorUnaryOpTest__ConvertToSingleInt32(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__ConvertToSingleInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Single[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleInt32 testClass) + { + var result = Vector128.ConvertToSingle(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__ConvertToSingleInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public VectorUnaryOpTest__ConvertToSingleInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Vector128.ConvertToSingle( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof(Vector128).GetMethod(nameof(Vector128.ConvertToSingle), new Type[] { + typeof(Vector128) + }); + + if (method is null) + { + method = typeof(Vector128).GetMethod(nameof(Vector128.ConvertToSingle), 1, new Type[] { + typeof(Vector128<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof(Single)); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Vector128.ConvertToSingle( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = Vector128.ConvertToSingle(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__ConvertToSingleInt32(); + var result = Vector128.ConvertToSingle(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Vector128.ConvertToSingle(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Vector128.ConvertToSingle(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != (float)(firstOp[0])) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != (float)(firstOp[i])) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Vector128)}.{nameof(Vector128.ConvertToSingle)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.Single.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.UInt32.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.Single.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.UInt32.cs index 1eda27aeb42442..4e153c5386cd08 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.Single.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToSingle.UInt32.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToSingleSingle() + private static void ConvertToSingleUInt32() { - var test = new VectorUnaryOpTest__ConvertToSingleSingle(); + var test = new VectorUnaryOpTest__ConvertToSingleUInt32(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToSingleSingle() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToSingleSingle + public sealed unsafe class VectorUnaryOpTest__ConvertToSingleUInt32 { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleSingle testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleUInt32 testClass) { var result = Vector128.ConvertToSingle(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleSingle testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToSingleSingle() + static VectorUnaryOpTest__ConvertToSingleUInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToSingleSingle() + public VectorUnaryOpTest__ConvertToSingleUInt32() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToSingleSingle(); + var test = new VectorUnaryOpTest__ConvertToSingleUInt32(); var result = Vector128.ConvertToSingle(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt32.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt32.Single.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt32.UInt32.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt32.Single.cs index ca7ac2e86c0b23..eea5b36f6a29c5 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt32.UInt32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt32.Single.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToUInt32UInt32() + private static void ConvertToUInt32Single() { - var test = new VectorUnaryOpTest__ConvertToUInt32UInt32(); + var test = new VectorUnaryOpTest__ConvertToUInt32Single(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToUInt32UInt32() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToUInt32UInt32 + public sealed unsafe class VectorUnaryOpTest__ConvertToUInt32Single { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32UInt32 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32Single testClass) { var result = Vector128.ConvertToUInt32(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32UInt32 testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToUInt32UInt32() + static VectorUnaryOpTest__ConvertToUInt32Single() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToUInt32UInt32() + public VectorUnaryOpTest__ConvertToUInt32Single() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToUInt32UInt32(); + var test = new VectorUnaryOpTest__ConvertToUInt32Single(); var result = Vector128.ConvertToUInt32(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt64.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt64.Double.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt64.UInt64.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt64.Double.cs index 5daaa41706b379..97d6baf2710964 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt64.UInt64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/ConvertToUInt64.Double.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToUInt64UInt64() + private static void ConvertToUInt64Double() { - var test = new VectorUnaryOpTest__ConvertToUInt64UInt64(); + var test = new VectorUnaryOpTest__ConvertToUInt64Double(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToUInt64UInt64() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToUInt64UInt64 + public sealed unsafe class VectorUnaryOpTest__ConvertToUInt64Double { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64UInt64 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64Double testClass) { var result = Vector128.ConvertToUInt64(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64UInt64 testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToUInt64UInt64() + static VectorUnaryOpTest__ConvertToUInt64Double() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToUInt64UInt64() + public VectorUnaryOpTest__ConvertToUInt64Double() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToUInt64UInt64(); + var test = new VectorUnaryOpTest__ConvertToUInt64Double(); var result = Vector128.ConvertToUInt64(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Program.Vector128.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Program.Vector128.cs index 89e18b139dd95d..8922def81ffa0a 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector128/Program.Vector128.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector128/Program.Vector128.cs @@ -73,14 +73,14 @@ static Program() ["ConditionalSelect.UInt16"] = ConditionalSelectUInt16, ["ConditionalSelect.UInt32"] = ConditionalSelectUInt32, ["ConditionalSelect.UInt64"] = ConditionalSelectUInt64, - ["ConvertToDouble.Double"] = ConvertToDoubleDouble, - ["ConvertToDouble.Double"] = ConvertToDoubleDouble, - ["ConvertToInt32.Int32"] = ConvertToInt32Int32, - ["ConvertToInt64.Int64"] = ConvertToInt64Int64, - ["ConvertToSingle.Single"] = ConvertToSingleSingle, - ["ConvertToSingle.Single"] = ConvertToSingleSingle, - ["ConvertToUInt32.UInt32"] = ConvertToUInt32UInt32, - ["ConvertToUInt64.UInt64"] = ConvertToUInt64UInt64, + ["ConvertToDouble.Int64"] = ConvertToDoubleInt64, + ["ConvertToDouble.UInt64"] = ConvertToDoubleUInt64, + ["ConvertToInt32.Single"] = ConvertToInt32Single, + ["ConvertToInt64.Double"] = ConvertToInt64Double, + ["ConvertToSingle.Int32"] = ConvertToSingleInt32, + ["ConvertToSingle.UInt32"] = ConvertToSingleUInt32, + ["ConvertToUInt32.Single"] = ConvertToUInt32Single, + ["ConvertToUInt64.Double"] = ConvertToUInt64Double, ["Create.Byte"] = CreateByte, ["Create.Double"] = CreateDouble, ["Create.Int16"] = CreateInt16, diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.Int64.cs new file mode 100644 index 00000000000000..fe9013bbd87972 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.Int64.cs @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void ConvertToDoubleInt64() + { + var test = new VectorUnaryOpTest__ConvertToDoubleInt64(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Double[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector256 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleInt64 testClass) + { + var result = Vector256.ConvertToDouble(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 32; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + + private static Vector256 _clsVar1; + + private Vector256 _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__ConvertToDoubleInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public VectorUnaryOpTest__ConvertToDoubleInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Vector256.ConvertToDouble( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof(Vector256).GetMethod(nameof(Vector256.ConvertToDouble), new Type[] { + typeof(Vector256) + }); + + if (method is null) + { + method = typeof(Vector256).GetMethod(nameof(Vector256.ConvertToDouble), 1, new Type[] { + typeof(Vector256<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof(Double)); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Vector256.ConvertToDouble( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = Vector256.ConvertToDouble(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__ConvertToDoubleInt64(); + var result = Vector256.ConvertToDouble(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Vector256.ConvertToDouble(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Vector256.ConvertToDouble(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult(Vector256 op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != (double)(firstOp[0])) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != (double)(firstOp[i])) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Vector256)}.{nameof(Vector256.ConvertToDouble)}(Vector256): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.Double.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.UInt64.cs similarity index 94% rename from src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.Double.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.UInt64.cs index dff3948ab50e8e..86254208e18a61 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.Double.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToDouble.UInt64.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToDoubleDouble() + private static void ConvertToDoubleUInt64() { - var test = new VectorUnaryOpTest__ConvertToDoubleDouble(); + var test = new VectorUnaryOpTest__ConvertToDoubleUInt64(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToDoubleDouble() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleDouble + public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleUInt64 { private struct DataTable { @@ -107,13 +107,13 @@ public static TestStruct Create() { var testStruct = new TestStruct(); - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleDouble testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleUInt64 testClass) { var result = Vector256.ConvertToDouble(_fld1); @@ -135,20 +135,20 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleDouble testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToDoubleDouble() + static VectorUnaryOpTest__ConvertToDoubleUInt64() { - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToDoubleDouble() + public VectorUnaryOpTest__ConvertToDoubleUInt64() { Succeeded = true; - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); } @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToDoubleDouble(); + var test = new VectorUnaryOpTest__ConvertToDoubleUInt64(); var result = Vector256.ConvertToDouble(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt32.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt32.Single.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt32.Int32.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt32.Single.cs index 569a73ea81a8f2..82a26d00455b22 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt32.Int32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt32.Single.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToInt32Int32() + private static void ConvertToInt32Single() { - var test = new VectorUnaryOpTest__ConvertToInt32Int32(); + var test = new VectorUnaryOpTest__ConvertToInt32Single(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToInt32Int32() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToInt32Int32 + public sealed unsafe class VectorUnaryOpTest__ConvertToInt32Single { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Int32 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Single testClass) { var result = Vector256.ConvertToInt32(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Int32 testClas private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToInt32Int32() + static VectorUnaryOpTest__ConvertToInt32Single() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToInt32Int32() + public VectorUnaryOpTest__ConvertToInt32Single() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToInt32Int32(); + var test = new VectorUnaryOpTest__ConvertToInt32Single(); var result = Vector256.ConvertToInt32(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt64.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt64.Double.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt64.Int64.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt64.Double.cs index 35a40c15a58574..250121dc448fe2 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt64.Int64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToInt64.Double.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToInt64Int64() + private static void ConvertToInt64Double() { - var test = new VectorUnaryOpTest__ConvertToInt64Int64(); + var test = new VectorUnaryOpTest__ConvertToInt64Double(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToInt64Int64() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToInt64Int64 + public sealed unsafe class VectorUnaryOpTest__ConvertToInt64Double { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Int64 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Double testClass) { var result = Vector256.ConvertToInt64(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Int64 testClas private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToInt64Int64() + static VectorUnaryOpTest__ConvertToInt64Double() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToInt64Int64() + public VectorUnaryOpTest__ConvertToInt64Double() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToInt64Int64(); + var test = new VectorUnaryOpTest__ConvertToInt64Double(); var result = Vector256.ConvertToInt64(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.Int32.cs new file mode 100644 index 00000000000000..902d6ddfddb677 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.Int32.cs @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void ConvertToSingleInt32() + { + var test = new VectorUnaryOpTest__ConvertToSingleInt32(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__ConvertToSingleInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Single[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector256 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleInt32 testClass) + { + var result = Vector256.ConvertToSingle(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 32; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector256 _clsVar1; + + private Vector256 _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__ConvertToSingleInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public VectorUnaryOpTest__ConvertToSingleInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Vector256.ConvertToSingle( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof(Vector256).GetMethod(nameof(Vector256.ConvertToSingle), new Type[] { + typeof(Vector256) + }); + + if (method is null) + { + method = typeof(Vector256).GetMethod(nameof(Vector256.ConvertToSingle), 1, new Type[] { + typeof(Vector256<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof(Single)); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Vector256.ConvertToSingle( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = Vector256.ConvertToSingle(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__ConvertToSingleInt32(); + var result = Vector256.ConvertToSingle(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Vector256.ConvertToSingle(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Vector256.ConvertToSingle(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult(Vector256 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != (float)(firstOp[0])) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != (float)(firstOp[i])) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Vector256)}.{nameof(Vector256.ConvertToSingle)}(Vector256): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.Single.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.UInt32.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.Single.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.UInt32.cs index 3c4cdbd8cb01d9..a5f8fbea9a822d 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.Single.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToSingle.UInt32.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToSingleSingle() + private static void ConvertToSingleUInt32() { - var test = new VectorUnaryOpTest__ConvertToSingleSingle(); + var test = new VectorUnaryOpTest__ConvertToSingleUInt32(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToSingleSingle() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToSingleSingle + public sealed unsafe class VectorUnaryOpTest__ConvertToSingleUInt32 { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleSingle testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleUInt32 testClass) { var result = Vector256.ConvertToSingle(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleSingle testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToSingleSingle() + static VectorUnaryOpTest__ConvertToSingleUInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToSingleSingle() + public VectorUnaryOpTest__ConvertToSingleUInt32() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToSingleSingle(); + var test = new VectorUnaryOpTest__ConvertToSingleUInt32(); var result = Vector256.ConvertToSingle(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt32.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt32.Single.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt32.UInt32.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt32.Single.cs index 32bb04d8674858..f3e7cc09372511 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt32.UInt32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt32.Single.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToUInt32UInt32() + private static void ConvertToUInt32Single() { - var test = new VectorUnaryOpTest__ConvertToUInt32UInt32(); + var test = new VectorUnaryOpTest__ConvertToUInt32Single(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToUInt32UInt32() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToUInt32UInt32 + public sealed unsafe class VectorUnaryOpTest__ConvertToUInt32Single { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32UInt32 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32Single testClass) { var result = Vector256.ConvertToUInt32(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32UInt32 testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToUInt32UInt32() + static VectorUnaryOpTest__ConvertToUInt32Single() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToUInt32UInt32() + public VectorUnaryOpTest__ConvertToUInt32Single() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToUInt32UInt32(); + var test = new VectorUnaryOpTest__ConvertToUInt32Single(); var result = Vector256.ConvertToUInt32(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt64.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt64.Double.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt64.UInt64.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt64.Double.cs index 8a1722650aa14f..90a46927a32f9f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt64.UInt64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/ConvertToUInt64.Double.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToUInt64UInt64() + private static void ConvertToUInt64Double() { - var test = new VectorUnaryOpTest__ConvertToUInt64UInt64(); + var test = new VectorUnaryOpTest__ConvertToUInt64Double(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToUInt64UInt64() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToUInt64UInt64 + public sealed unsafe class VectorUnaryOpTest__ConvertToUInt64Double { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64UInt64 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64Double testClass) { var result = Vector256.ConvertToUInt64(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64UInt64 testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToUInt64UInt64() + static VectorUnaryOpTest__ConvertToUInt64Double() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToUInt64UInt64() + public VectorUnaryOpTest__ConvertToUInt64Double() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToUInt64UInt64(); + var test = new VectorUnaryOpTest__ConvertToUInt64Double(); var result = Vector256.ConvertToUInt64(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Program.Vector256.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Program.Vector256.cs index 89e18b139dd95d..8922def81ffa0a 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Program.Vector256.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Program.Vector256.cs @@ -73,14 +73,14 @@ static Program() ["ConditionalSelect.UInt16"] = ConditionalSelectUInt16, ["ConditionalSelect.UInt32"] = ConditionalSelectUInt32, ["ConditionalSelect.UInt64"] = ConditionalSelectUInt64, - ["ConvertToDouble.Double"] = ConvertToDoubleDouble, - ["ConvertToDouble.Double"] = ConvertToDoubleDouble, - ["ConvertToInt32.Int32"] = ConvertToInt32Int32, - ["ConvertToInt64.Int64"] = ConvertToInt64Int64, - ["ConvertToSingle.Single"] = ConvertToSingleSingle, - ["ConvertToSingle.Single"] = ConvertToSingleSingle, - ["ConvertToUInt32.UInt32"] = ConvertToUInt32UInt32, - ["ConvertToUInt64.UInt64"] = ConvertToUInt64UInt64, + ["ConvertToDouble.Int64"] = ConvertToDoubleInt64, + ["ConvertToDouble.UInt64"] = ConvertToDoubleUInt64, + ["ConvertToInt32.Single"] = ConvertToInt32Single, + ["ConvertToInt64.Double"] = ConvertToInt64Double, + ["ConvertToSingle.Int32"] = ConvertToSingleInt32, + ["ConvertToSingle.UInt32"] = ConvertToSingleUInt32, + ["ConvertToUInt32.Single"] = ConvertToUInt32Single, + ["ConvertToUInt64.Double"] = ConvertToUInt64Double, ["Create.Byte"] = CreateByte, ["Create.Double"] = CreateDouble, ["Create.Int16"] = CreateInt16, diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.Int64.cs new file mode 100644 index 00000000000000..434e74bc4bcac9 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.Int64.cs @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void ConvertToDoubleInt64() + { + var test = new VectorUnaryOpTest__ConvertToDoubleInt64(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Double[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleInt64 testClass) + { + var result = Vector64.ConvertToDouble(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__ConvertToDoubleInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public VectorUnaryOpTest__ConvertToDoubleInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Vector64.ConvertToDouble( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof(Vector64).GetMethod(nameof(Vector64.ConvertToDouble), new Type[] { + typeof(Vector64) + }); + + if (method is null) + { + method = typeof(Vector64).GetMethod(nameof(Vector64.ConvertToDouble), 1, new Type[] { + typeof(Vector64<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof(Double)); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Vector64.ConvertToDouble( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = Vector64.ConvertToDouble(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__ConvertToDoubleInt64(); + var result = Vector64.ConvertToDouble(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Vector64.ConvertToDouble(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Vector64.ConvertToDouble(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != (double)(firstOp[0])) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != (double)(firstOp[i])) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Vector64)}.{nameof(Vector64.ConvertToDouble)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.Double.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.UInt64.cs similarity index 94% rename from src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.Double.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.UInt64.cs index 95410e322a7117..fd51e78150e1ae 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.Double.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToDouble.UInt64.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToDoubleDouble() + private static void ConvertToDoubleUInt64() { - var test = new VectorUnaryOpTest__ConvertToDoubleDouble(); + var test = new VectorUnaryOpTest__ConvertToDoubleUInt64(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToDoubleDouble() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleDouble + public sealed unsafe class VectorUnaryOpTest__ConvertToDoubleUInt64 { private struct DataTable { @@ -107,13 +107,13 @@ public static TestStruct Create() { var testStruct = new TestStruct(); - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleDouble testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleUInt64 testClass) { var result = Vector64.ConvertToDouble(_fld1); @@ -135,20 +135,20 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToDoubleDouble testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToDoubleDouble() + static VectorUnaryOpTest__ConvertToDoubleUInt64() { - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToDoubleDouble() + public VectorUnaryOpTest__ConvertToDoubleUInt64() { Succeeded = true; - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); - for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = Math.Min(long.MaxValue, TestLibrary.Generator.GetUInt64()); } _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize); } @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToDoubleDouble(); + var test = new VectorUnaryOpTest__ConvertToDoubleUInt64(); var result = Vector64.ConvertToDouble(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt32.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt32.Single.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt32.Int32.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt32.Single.cs index 521a79dfb1ba2c..d38c1856993f5d 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt32.Int32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt32.Single.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToInt32Int32() + private static void ConvertToInt32Single() { - var test = new VectorUnaryOpTest__ConvertToInt32Int32(); + var test = new VectorUnaryOpTest__ConvertToInt32Single(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToInt32Int32() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToInt32Int32 + public sealed unsafe class VectorUnaryOpTest__ConvertToInt32Single { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Int32 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Single testClass) { var result = Vector64.ConvertToInt32(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt32Int32 testClas private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToInt32Int32() + static VectorUnaryOpTest__ConvertToInt32Single() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToInt32Int32() + public VectorUnaryOpTest__ConvertToInt32Single() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToInt32Int32(); + var test = new VectorUnaryOpTest__ConvertToInt32Single(); var result = Vector64.ConvertToInt32(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt64.Int64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt64.Double.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt64.Int64.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt64.Double.cs index 303c872d583a44..139da25fb67aa1 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt64.Int64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToInt64.Double.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToInt64Int64() + private static void ConvertToInt64Double() { - var test = new VectorUnaryOpTest__ConvertToInt64Int64(); + var test = new VectorUnaryOpTest__ConvertToInt64Double(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToInt64Int64() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToInt64Int64 + public sealed unsafe class VectorUnaryOpTest__ConvertToInt64Double { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Int64 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Double testClass) { var result = Vector64.ConvertToInt64(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToInt64Int64 testClas private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToInt64Int64() + static VectorUnaryOpTest__ConvertToInt64Double() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToInt64Int64() + public VectorUnaryOpTest__ConvertToInt64Double() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToInt64Int64(); + var test = new VectorUnaryOpTest__ConvertToInt64Double(); var result = Vector64.ConvertToInt64(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.Int32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.Int32.cs new file mode 100644 index 00000000000000..f0c6f3736114b0 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.Int32.cs @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; + +namespace JIT.HardwareIntrinsics.General +{ + public static partial class Program + { + private static void ConvertToSingleInt32() + { + var test = new VectorUnaryOpTest__ConvertToSingleInt32(); + + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class VectorUnaryOpTest__ConvertToSingleInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Single[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 32 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleInt32 testClass) + { + var result = Vector64.ConvertToSingle(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static VectorUnaryOpTest__ConvertToSingleInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public VectorUnaryOpTest__ConvertToSingleInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize); + } + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Vector64.ConvertToSingle( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var method = typeof(Vector64).GetMethod(nameof(Vector64.ConvertToSingle), new Type[] { + typeof(Vector64) + }); + + if (method is null) + { + method = typeof(Vector64).GetMethod(nameof(Vector64.ConvertToSingle), 1, new Type[] { + typeof(Vector64<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) + }); + } + + if (method.IsGenericMethodDefinition) + { + method = method.MakeGenericMethod(typeof(Single)); + } + + var result = method.Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Vector64.ConvertToSingle( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = Vector64.ConvertToSingle(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new VectorUnaryOpTest__ConvertToSingleInt32(); + var result = Vector64.ConvertToSingle(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Vector64.ConvertToSingle(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Vector64.ConvertToSingle(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != (float)(firstOp[0])) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != (float)(firstOp[i])) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Vector64)}.{nameof(Vector64.ConvertToSingle)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.Single.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.UInt32.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.Single.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.UInt32.cs index 4a1673f667733c..4e52f26dc79a6f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.Single.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToSingle.UInt32.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToSingleSingle() + private static void ConvertToSingleUInt32() { - var test = new VectorUnaryOpTest__ConvertToSingleSingle(); + var test = new VectorUnaryOpTest__ConvertToSingleUInt32(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToSingleSingle() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToSingleSingle + public sealed unsafe class VectorUnaryOpTest__ConvertToSingleUInt32 { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleSingle testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleUInt32 testClass) { var result = Vector64.ConvertToSingle(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToSingleSingle testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToSingleSingle() + static VectorUnaryOpTest__ConvertToSingleUInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToSingleSingle() + public VectorUnaryOpTest__ConvertToSingleUInt32() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToSingleSingle(); + var test = new VectorUnaryOpTest__ConvertToSingleUInt32(); var result = Vector64.ConvertToSingle(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt32.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt32.Single.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt32.UInt32.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt32.Single.cs index 314417d948647f..37c6d5c32a3147 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt32.UInt32.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt32.Single.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToUInt32UInt32() + private static void ConvertToUInt32Single() { - var test = new VectorUnaryOpTest__ConvertToUInt32UInt32(); + var test = new VectorUnaryOpTest__ConvertToUInt32Single(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToUInt32UInt32() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToUInt32UInt32 + public sealed unsafe class VectorUnaryOpTest__ConvertToUInt32Single { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32UInt32 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32Single testClass) { var result = Vector64.ConvertToUInt32(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt32UInt32 testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToUInt32UInt32() + static VectorUnaryOpTest__ConvertToUInt32Single() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToUInt32UInt32() + public VectorUnaryOpTest__ConvertToUInt32Single() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToUInt32UInt32(); + var test = new VectorUnaryOpTest__ConvertToUInt32Single(); var result = Vector64.ConvertToUInt32(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt64.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt64.Double.cs similarity index 97% rename from src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt64.UInt64.cs rename to src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt64.Double.cs index 12abbb8843356d..4cc3ca81f69701 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt64.UInt64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/ConvertToUInt64.Double.cs @@ -17,9 +17,9 @@ namespace JIT.HardwareIntrinsics.General { public static partial class Program { - private static void ConvertToUInt64UInt64() + private static void ConvertToUInt64Double() { - var test = new VectorUnaryOpTest__ConvertToUInt64UInt64(); + var test = new VectorUnaryOpTest__ConvertToUInt64Double(); // Validates basic functionality works, using Unsafe.Read test.RunBasicScenario_UnsafeRead(); @@ -52,7 +52,7 @@ private static void ConvertToUInt64UInt64() } } - public sealed unsafe class VectorUnaryOpTest__ConvertToUInt64UInt64 + public sealed unsafe class VectorUnaryOpTest__ConvertToUInt64Double { private struct DataTable { @@ -113,7 +113,7 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64UInt64 testClass) + public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64Double testClass) { var result = Vector64.ConvertToUInt64(_fld1); @@ -135,13 +135,13 @@ public void RunStructFldScenario(VectorUnaryOpTest__ConvertToUInt64UInt64 testCl private DataTable _dataTable; - static VectorUnaryOpTest__ConvertToUInt64UInt64() + static VectorUnaryOpTest__ConvertToUInt64Double() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public VectorUnaryOpTest__ConvertToUInt64UInt64() + public VectorUnaryOpTest__ConvertToUInt64Double() { Succeeded = true; @@ -221,7 +221,7 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new VectorUnaryOpTest__ConvertToUInt64UInt64(); + var test = new VectorUnaryOpTest__ConvertToUInt64Double(); var result = Vector64.ConvertToUInt64(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Program.Vector64.cs b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Program.Vector64.cs index 82755818253168..c000608c2bef6f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Program.Vector64.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Program.Vector64.cs @@ -73,14 +73,14 @@ static Program() ["ConditionalSelect.UInt16"] = ConditionalSelectUInt16, ["ConditionalSelect.UInt32"] = ConditionalSelectUInt32, ["ConditionalSelect.UInt64"] = ConditionalSelectUInt64, - ["ConvertToDouble.Double"] = ConvertToDoubleDouble, - ["ConvertToDouble.Double"] = ConvertToDoubleDouble, - ["ConvertToInt32.Int32"] = ConvertToInt32Int32, - ["ConvertToInt64.Int64"] = ConvertToInt64Int64, - ["ConvertToSingle.Single"] = ConvertToSingleSingle, - ["ConvertToSingle.Single"] = ConvertToSingleSingle, - ["ConvertToUInt32.UInt32"] = ConvertToUInt32UInt32, - ["ConvertToUInt64.UInt64"] = ConvertToUInt64UInt64, + ["ConvertToDouble.Int64"] = ConvertToDoubleInt64, + ["ConvertToDouble.UInt64"] = ConvertToDoubleUInt64, + ["ConvertToInt32.Single"] = ConvertToInt32Single, + ["ConvertToInt64.Double"] = ConvertToInt64Double, + ["ConvertToSingle.Int32"] = ConvertToSingleInt32, + ["ConvertToSingle.UInt32"] = ConvertToSingleUInt32, + ["ConvertToUInt32.Single"] = ConvertToUInt32Single, + ["ConvertToUInt64.Double"] = ConvertToUInt64Double, ["Create.Byte"] = CreateByte, ["Create.Double"] = CreateDouble, ["Create.Int16"] = CreateInt16,