diff options
53 files changed, 12372 insertions, 246 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 7b9313ae54..7bee3bfcdd 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -3059,14 +3059,6 @@ protected: CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, bool mustExpand); - GenTree* impSSE3Intrinsic(NamedIntrinsic intrinsic, - CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig, - bool mustExpand); - GenTree* impSSSE3Intrinsic(NamedIntrinsic intrinsic, - CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig, - bool mustExpand); GenTree* impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, @@ -3125,6 +3117,7 @@ protected: GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType); static bool isImmHWIntrinsic(NamedIntrinsic intrinsic, GenTree* lastOp); GenTree* addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand); + bool hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, HWIntrinsicFlag flags); #endif // _TARGET_XARCH_ #ifdef _TARGET_ARM64_ InstructionSet lookupHWIntrinsicISA(const char* className); diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index 64a76357c1..4ffe342c99 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -155,7 +155,10 @@ bool emitter::IsDstDstSrcAVXInstruction(instruction ins) case INS_phsubd: case INS_phsubsw: case INS_phsubw: + case INS_pinsrb: case INS_pinsrw: + case INS_pinsrd: + case INS_pinsrq: case INS_pmaddubsw: case INS_pmaddwd: case INS_pmaxsb: @@ -383,9 +386,16 @@ bool TakesRexWPrefix(instruction ins, emitAttr attr) // size specification (128 vs. 256 bits) and the operand size specification (32 vs. 64 bits), where both are // required, the instruction must be created with the register size attribute (EA_16BYTE or EA_32BYTE), // and here we must special case these by the opcode. - if (ins == INS_vpermq || ins == INS_vpsrlvq || ins == INS_vpsllvq) + switch (ins) { - return true; + case INS_vpermq: + case INS_vpsrlvq: + case INS_vpsllvq: + case INS_pinsrq: + case INS_pextrq: + return true; + default: + break; } #endif // !LEGACY_BACKEND #ifdef _TARGET_AMD64_ @@ -1084,7 +1094,7 @@ bool emitter::emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id) if (!IsSSEOrAVXInstruction(ins) || ins == INS_mov_xmm2i || ins == INS_cvttsd2si #ifndef LEGACY_BACKEND || ins == INS_cvttss2si || ins == INS_cvtsd2si || ins == INS_cvtss2si || ins == INS_pmovmskb || - ins == INS_pextrw + ins == INS_pextrw || ins == INS_pextrb || ins == INS_pextrd || ins == INS_pextrq || ins == INS_extractps #endif // !LEGACY_BACKEND ) { @@ -4034,6 +4044,12 @@ void emitter::emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regN sz += emitGetRexPrefixSize(ins); } + if ((ins == INS_pextrq || ins == INS_pinsrq) && !UseVEXEncoding()) + { + assert(UseSSE4()); + sz += 1; + } + id->idIns(ins); id->idInsFmt(IF_RRW_RRW_CNS); id->idReg1(reg1); @@ -5519,11 +5535,26 @@ static bool isSseShift(instruction ins) } } +static bool isSSEExtract(instruction ins) +{ + switch (ins) + { + case INS_pextrb: + case INS_pextrw: + case INS_pextrd: + case INS_pextrq: + case INS_extractps: + return true; + default: + return false; + } +} + void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int ival) { // TODO-XARCH refactoring emitIns_R_R_I to handle SSE2/AVX2 shift as well as emitIns_R_I bool isShift = isSseShift(ins); - if (UseVEXEncoding() && !isShift) + if (isSSEExtract(ins) || (UseVEXEncoding() && !isShift)) { emitIns_R_R_I(ins, attr, reg, reg1, ival); } diff --git a/src/jit/hwintrinsiccodegenxarch.cpp b/src/jit/hwintrinsiccodegenxarch.cpp index eb7a9134ce..2f0e5f8c41 100644 --- a/src/jit/hwintrinsiccodegenxarch.cpp +++ b/src/jit/hwintrinsiccodegenxarch.cpp @@ -36,10 +36,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX static bool genIsTableDrivenHWIntrinsic(HWIntrinsicCategory category, HWIntrinsicFlag flags) { // TODO - make more categories to the table-driven framework - // HW_Category_Helper and HW_Flag_MultiIns usually need manual codegen + // HW_Category_Helper and HW_Flag_MultiIns/HW_Flag_SpecialCodeGen usually need manual codegen const bool tableDrivenCategory = category != HW_Category_Special && category != HW_Category_Scalar && category != HW_Category_Helper; - const bool tableDrivenFlag = (flags & HW_Flag_MultiIns) == 0; + const bool tableDrivenFlag = (flags & (HW_Flag_MultiIns | HW_Flag_SpecialCodeGen)) == 0; return tableDrivenCategory && tableDrivenFlag; } @@ -119,6 +119,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } else if (Compiler::isImmHWIntrinsic(intrinsicID, op2)) { + if (intrinsicID == NI_SSE2_Extract) + { + // extract instructions return to GP-registers, so it needs int size as the emitsize + simdSize = emitTypeSize(TYP_INT); + } auto emitSwCase = [&](unsigned i) { emit->emitIns_SIMD_R_R_I(ins, simdSize, targetReg, op1Reg, (int)i); }; @@ -605,17 +610,6 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) switch (intrinsicID) { - case NI_SSE_ConvertScalarToVector128Single: - { - assert(node->TypeGet() == TYP_SIMD16); - assert(node->gtSIMDBaseType == TYP_FLOAT); - assert(Compiler::ivalOfHWIntrinsic(intrinsicID) == -1); - - instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType); - genHWIntrinsic_R_R_RM(node, ins); - break; - } - case NI_SSE_CompareEqualOrderedScalar: case NI_SSE_CompareEqualUnorderedScalar: { @@ -985,19 +979,14 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) assert(op2 == nullptr); assert(baseType == TYP_DOUBLE || baseType == TYP_FLOAT || baseType == TYP_INT || baseType == TYP_UINT || baseType == TYP_LONG || baseType == TYP_ULONG); - if (op1Reg != targetReg) + instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType); + if (baseType == TYP_DOUBLE || baseType == TYP_FLOAT) { - instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType); - if (baseType == TYP_DOUBLE || baseType == TYP_FLOAT) - { - emit->emitIns_R_R(ins, emitTypeSize(targetType), targetReg, op1Reg); - } - else - { - // TODO-XArch-Bug https://github.com/dotnet/coreclr/issues/16329 - // using hardcoded instruction as workaround for inexact type conversions - emit->emitIns_R_R(INS_mov_xmm2i, emitActualTypeSize(baseType), op1Reg, targetReg); - } + emit->emitIns_R_R(ins, emitTypeSize(targetType), targetReg, op1Reg); + } + else + { + emit->emitIns_R_R(ins, emitActualTypeSize(baseType), op1Reg, targetReg); } break; } @@ -1144,6 +1133,44 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) break; } + case NI_SSE41_Extract: + { + regNumber tmpTargetReg = REG_NA; + instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType); + if (baseType == TYP_FLOAT) + { + tmpTargetReg = node->ExtractTempReg(); + } + auto emitSwCase = [&](unsigned i) { + if (baseType == TYP_FLOAT) + { + // extract instructions return to GP-registers, so it needs int size as the emitsize + emit->emitIns_SIMD_R_R_I(ins, emitTypeSize(TYP_INT), op1Reg, tmpTargetReg, (int)i); + emit->emitIns_R_R(INS_mov_i2xmm, EA_4BYTE, targetReg, tmpTargetReg); + } + else + { + emit->emitIns_SIMD_R_R_I(ins, emitTypeSize(TYP_INT), targetReg, op1Reg, (int)i); + } + }; + + if (op2->IsCnsIntOrI()) + { + ssize_t ival = op2->AsIntCon()->IconValue(); + emitSwCase((unsigned)ival); + } + else + { + // We emit a fallback case for the scenario when the imm-op is not a constant. This should + // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it + // can also occur if the consumer calls it directly and just doesn't pass a constant value. + regNumber baseReg = node->ExtractTempReg(); + regNumber offsReg = node->GetSingleTempReg(); + genHWIntrinsicJumpTableFallback(intrinsicID, op2->gtRegNum, baseReg, offsReg, emitSwCase); + } + break; + } + default: unreached(); break; diff --git a/src/jit/hwintrinsiclistxarch.h b/src/jit/hwintrinsiclistxarch.h index 69366edec3..5365c6e3d0 100644 --- a/src/jit/hwintrinsiclistxarch.h +++ b/src/jit/hwintrinsiclistxarch.h @@ -33,29 +33,29 @@ HARDWARE_INTRINSIC(SSE_AddScalar, "AddScalar" HARDWARE_INTRINSIC(SSE_And, "And", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE_AndNot, "AndNot", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE_CompareEqual, "CompareEqual", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareEqualScalar, "CompareEqualScalar", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareGreaterThan, "CompareGreaterThan", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareGreaterThanScalar, "CompareGreaterThanScalar", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqual, "CompareGreaterThanOrEqual", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualScalar, "CompareGreaterThanOrEqualScalar", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareLessThan, "CompareLessThan", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareLessThanScalar, "CompareLessThanScalar", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqual, "CompareLessThanOrEqual", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualScalar, "CompareLessThanOrEqualScalar", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareNotEqual, "CompareNotEqual", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareNotEqualScalar, "CompareNotEqualScalar", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareNotGreaterThan, "CompareNotGreaterThan", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanScalar, "CompareNotGreaterThanScalar", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanOrEqual, "CompareNotGreaterThanOrEqual", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) @@ -68,12 +68,12 @@ HARDWARE_INTRINSIC(SSE_CompareOrdered, "CompareOrd HARDWARE_INTRINSIC(SSE_CompareOrderedScalar, "CompareOrderedScalar", SSE, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareUnordered, "CompareUnordered", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE_CompareUnorderedScalar, "CompareUnorderedScalar", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_ConvertToInt32, "ConvertToInt32", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_ConvertToInt64, "ConvertToInt64", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_ConvertToSingle, "ConvertToSingle", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_Helper, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_ConvertToInt32, "ConvertToInt32", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_ConvertToInt64, "ConvertToInt64", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_ConvertToSingle, "ConvertToSingle", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SecondArgMaybe64Bit|HW_Flag_BaseTypeFromFirstArg|HW_Flag_CopyUpperBits|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_64BitOnly|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_Divide, "Divide", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE_DivideScalar, "DivideScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_LoadAlignedVector128, "LoadAlignedVector128", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movaps, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) @@ -134,29 +134,29 @@ HARDWARE_INTRINSIC(SSE2_And, "And", HARDWARE_INTRINSIC(SSE2_AndNot, "AndNot", SSE2, -1, 16, 2, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_Average, "Average", SSE2, -1, 16, 2, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE2_CompareEqual, "CompareEqual", SSE2, 0, 16, 2, {INS_pcmpeqb, INS_pcmpeqb, INS_pcmpeqw, INS_pcmpeqw, INS_pcmpeqd, INS_pcmpeqd, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareEqualScalar, "CompareEqualScalar", SSE2, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareGreaterThan, "CompareGreaterThan", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareGreaterThanScalar, "CompareGreaterThanScalar", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqual, "CompareGreaterThanOrEqual", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualScalar, "CompareGreaterThanOrEqualScalar", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareLessThan, "CompareLessThan", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_Special, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareLessThanScalar, "CompareLessThanScalar", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromArg|HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareLessThanScalar, "CompareLessThanScalar", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqual, "CompareLessThanOrEqual", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualScalar, "CompareLessThanOrEqualScalar", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareNotEqual, "CompareNotEqual", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareNotEqualScalar, "CompareNotEqualScalar", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThan, "CompareNotGreaterThan", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanScalar, "CompareNotGreaterThanScalar", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanOrEqual, "CompareNotGreaterThanOrEqual", SSE2, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) @@ -169,25 +169,27 @@ HARDWARE_INTRINSIC(SSE2_CompareOrdered, "CompareOrd HARDWARE_INTRINSIC(SSE2_CompareOrderedScalar, "CompareOrderedScalar", SSE2, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareUnordered, "CompareUnordered", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_CompareUnorderedScalar, "CompareUnorderedScalar", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_ConvertToDouble, "ConvertToDouble", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsd}, HW_Category_Helper, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToInt32, "ConvertToInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToInt64, "ConvertToInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToUInt32, "ConvertToUInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToUInt64, "ConvertToUInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToVector128Double, "ConvertToVector128Double", SSE2, -1, 16, 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_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Double, "ConvertScalarToVector128Double", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtss2sd, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32, "ConvertToVector128Int32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToDouble, "ConvertToDouble", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsd}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToInt32, "ConvertToInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToInt64, "ConvertToInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_64BitOnly|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToUInt32, "ConvertToUInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToUInt64, "ConvertToUInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToVector128Double, "ConvertToVector128Double", SSE2, -1, 16, 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(SSE2_ConvertScalarToVector128Double, "ConvertScalarToVector128Double", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtss2sd, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SecondArgMaybe64Bit|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32, "ConvertToVector128Int32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Int32, "ConvertScalarToVector128Int32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32WithTruncation, "ConvertToVector128Int32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Int64, "ConvertScalarToVector128Int64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertToVector128Single, "ConvertToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2ss}, HW_Category_Special, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32WithTruncation, "ConvertToVector128Int32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Int64, "ConvertScalarToVector128Int64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_64BitOnly|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertToVector128Single, "ConvertToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2ss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128UInt32, "ConvertScalarToVector128UInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128UInt64, "ConvertScalarToVector128UInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128UInt64, "ConvertScalarToVector128UInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_64BitOnly|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_Divide, "Divide", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_DivideScalar, "DivideScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_Extract, "Extract", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pextrw, INS_pextrw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_Insert, "Insert", SSE2, -1, 16, 3, {INS_invalid, INS_invalid, INS_pinsrw, INS_pinsrw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(SSE2_LoadAlignedVector128, "LoadAlignedVector128", SSE2, -1, 16, 1, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_LoadFence, "LoadFence", SSE2, -1, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_LoadScalarVector128, "LoadScalarVector128", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_movd, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) @@ -200,16 +202,16 @@ HARDWARE_INTRINSIC(SSE2_Min, "Min", HARDWARE_INTRINSIC(SSE2_MinScalar, "MinScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_MoveMask, "MoveMask", SSE2, -1, 16, 1, {INS_pmovmskb, INS_pmovmskb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskpd}, HW_Category_Special, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_MoveScalar, "MoveScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE2_Multiply, "Multiply", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuludq, INS_invalid, INS_invalid, INS_invalid, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromArg) +HARDWARE_INTRINSIC(SSE2_Multiply, "Multiply", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuludq, INS_invalid, INS_invalid, INS_invalid, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(SSE2_MultiplyHigh, "MultiplyHigh", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2_MultiplyHorizontalAdd, "MultiplyHorizontalAdd", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromArg) +HARDWARE_INTRINSIC(SSE2_MultiplyHorizontalAdd, "MultiplyHorizontalAdd", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(SSE2_MultiplyLow, "MultiplyLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmullw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE2_MultiplyScalar, "MultiplyScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_Or, "Or", SSE2, -1, 16, 2, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_invalid, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2_PackSignedSaturate, "PackSignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg) -HARDWARE_INTRINSIC(SSE2_PackUnsignedSaturate, "PackUnsignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg) +HARDWARE_INTRINSIC(SSE2_PackSignedSaturate, "PackSignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(SSE2_PackUnsignedSaturate, "PackUnsignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(SSE2_SetZeroVector128, "SetZeroVector128", SSE2, -1, 16, 0, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_invalid, INS_xorpd}, HW_Category_Helper, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_SumAbsoluteDifferences, "SumAbsoluteDifferences", SSE2, -1, 16, 2, {INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg) +HARDWARE_INTRINSIC(SSE2_SumAbsoluteDifferences, "SumAbsoluteDifferences", SSE2, -1, 16, 2, {INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(SSE2_ShiftLeftLogical, "ShiftLeftLogical", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(SSE2_ShiftLeftLogical128BitLane, "ShiftLeftLogical128BitLane", SSE2, -1, 16, 2, {INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(SSE2_ShiftRightArithmetic, "ShiftRightArithmetic", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_psrad, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) @@ -273,12 +275,14 @@ HARDWARE_INTRINSIC(SSE41_BlendVariable, "BlendVaria HARDWARE_INTRINSIC(SSE41_Ceiling, "Ceiling", SSE41, 10, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_CeilingScalar, "CeilingScalar", SSE41, 10, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE41_CompareEqual, "CompareEqual", SSE41, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpeqq, INS_pcmpeqq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int16, "ConvertToVector128Int16", SSE41, -1, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int32, "ConvertToVector128Int32", SSE41, -1, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int64, "ConvertToVector128Int64", SSE41, -1, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int16, "ConvertToVector128Int16", SSE41, -1, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int32, "ConvertToVector128Int32", SSE41, -1, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int64, "ConvertToVector128Int64", SSE41, -1, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_DotProduct, "DotProduct", SSE41, -1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_dppd}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(SSE41_Extract, "Extract", SSE41, -1, 16, 2, {INS_pextrb, INS_pextrb, INS_invalid, INS_invalid, INS_pextrd, INS_pextrd, INS_pextrq, INS_pextrq, INS_extractps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiIns|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_Floor, "Floor", SSE41, 9, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_FloorScalar, "FloorScalar", SSE41, 9, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE41_Insert, "Insert", SSE41, -1, 16, 3, {INS_pinsrb, INS_pinsrb, INS_invalid, INS_invalid, INS_pinsrd, INS_pinsrd, INS_pinsrq, INS_pinsrq, INS_insertps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_SecondArgMaybe64Bit) HARDWARE_INTRINSIC(SSE41_LoadAlignedVector128NonTemporal, "LoadAlignedVector128NonTemporal", SSE41, -1, 16, 1, {INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_Max, "Max", SSE41, -1, 16, 2, {INS_pmaxsb, INS_invalid, INS_invalid, INS_pmaxuw, INS_pmaxsd, INS_pmaxud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE41_Min, "Min", SSE41, -1, 16, 2, {INS_pminsb, INS_invalid, INS_invalid, INS_pminuw, INS_pminsd, INS_pminud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) @@ -297,12 +301,12 @@ HARDWARE_INTRINSIC(SSE41_RoundToPositiveInfinity, "RoundToPos HARDWARE_INTRINSIC(SSE41_RoundToPositiveInfinityScalar, "RoundToPositiveInfinityScalar", SSE41, 10, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE41_RoundToZero, "RoundToZero", SSE41, 11, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_RoundToZeroScalar, "RoundToZeroScalar", SSE41, 11, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE41_TestAllOnes, "TestAllOnes", SSE41, -1, 16, 1, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41_TestAllZeros, "TestAllZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE41_TestC, "TestC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE41_TestMixOnesZeros, "TestMixOnesZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE41_TestNotZAndNotC, "TestNotZAndNotC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE41_TestZ, "TestZ", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment) +HARDWARE_INTRINSIC(SSE41_TestAllOnes, "TestAllOnes", SSE41, -1, 16, 1, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(SSE41_TestAllZeros, "TestAllZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(SSE41_TestC, "TestC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(SSE41_TestMixOnesZeros, "TestMixOnesZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(SSE41_TestNotZAndNotC, "TestNotZAndNotC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(SSE41_TestZ, "TestZ", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) // SSE42 Intrinsics HARDWARE_INTRINSIC(SSE42_IsSupported, "get_IsSupported", SSE42, -1, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IsSupportedProperty, HW_Flag_NoFlag) @@ -352,9 +356,9 @@ HARDWARE_INTRINSIC(AVX_Store, "Store", HARDWARE_INTRINSIC(AVX_StoreAligned, "StoreAligned", AVX, -1, 32, 2, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", AVX, -1, 32, 2, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntps, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX_Subtract, "Subtract", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX_TestC, "TestC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg) -HARDWARE_INTRINSIC(AVX_TestNotZAndNotC, "TestNotZAndNotC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg) -HARDWARE_INTRINSIC(AVX_TestZ, "TestZ", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg) +HARDWARE_INTRINSIC(AVX_TestC, "TestC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX_TestNotZAndNotC, "TestNotZAndNotC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX_TestZ, "TestZ", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AVX_UnpackHigh, "UnpackHigh", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX_UnpackLow, "UnpackLow", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpcklps, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX_Xor, "Xor", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) diff --git a/src/jit/hwintrinsicxarch.cpp b/src/jit/hwintrinsicxarch.cpp index 36f48ba732..86a9489be0 100644 --- a/src/jit/hwintrinsicxarch.cpp +++ b/src/jit/hwintrinsicxarch.cpp @@ -200,12 +200,22 @@ unsigned Compiler::simdSizeOfHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_SIG_I return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].simdSize; } - CORINFO_CLASS_HANDLE typeHnd = - ((flags & HW_Flag_BaseTypeFromArg) == 0) ? sig->retTypeSigClass : info.compCompHnd->getArgClass(sig, sig->args); + CORINFO_CLASS_HANDLE typeHnd = nullptr; - int simdSize = getSIMDTypeSizeInBytes(typeHnd); - assert(simdSize > 0); - return (unsigned)simdSize; + if (JITtype2varType(sig->retType) == TYP_STRUCT) + { + typeHnd = sig->retTypeSigClass; + } + else + { + assert((flags & HW_Flag_BaseTypeFromFirstArg) != 0); + typeHnd = info.compCompHnd->getArgClass(sig, sig->args); + } + + unsigned simdSize = 0; + var_types baseType = getBaseTypeAndSizeOfSIMDType(typeHnd, &simdSize); + assert(simdSize > 0 && baseType != TYP_UNKNOWN); + return simdSize; } //------------------------------------------------------------------------ @@ -486,7 +496,6 @@ bool Compiler::isFullyImplmentedISAClass(InstructionSet isa) switch (isa) { case InstructionSet_SSE2: - case InstructionSet_SSE41: case InstructionSet_SSE42: case InstructionSet_AVX: case InstructionSet_AVX2: @@ -500,6 +509,7 @@ bool Compiler::isFullyImplmentedISAClass(InstructionSet isa) case InstructionSet_SSE: case InstructionSet_SSE3: case InstructionSet_SSSE3: + case InstructionSet_SSE41: case InstructionSet_LZCNT: case InstructionSet_POPCNT: return true; @@ -551,10 +561,37 @@ bool Compiler::compSupportsHWIntrinsic(InstructionSet isa) isFullyImplmentedISAClass(isa)); } -static bool isTypeSupportedForIntrinsic(var_types type) +//------------------------------------------------------------------------ +// hwIntrinsicSignatureTypeSupported: platform support of hardware intrinsics +// +// Arguments: +// retType - return type +// sig - intrinsic signature +// flags - flags of the intrinsics +// +// Return Value: +// Returns true iff the given type signature is supported +// Notes: +// - This is only used on 32-bit systems to determine whether the signature uses no 64-bit registers. +// - The `retType` is passed to avoid another call to the type system, as it has already been retrieved. +bool Compiler::hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, HWIntrinsicFlag flags) { #ifdef _TARGET_X86_ - return !varTypeIsLong(type); + CORINFO_CLASS_HANDLE argClass; + + if ((flags & HW_Flag_64BitOnly) != 0) + { + return false; + } + else if ((flags & HW_Flag_SecondArgMaybe64Bit) != 0) + { + assert(sig->numArgs >= 2); + CorInfoType corType = + strip(info.compCompHnd->getArgType(sig, info.compCompHnd->getArgNext(sig->args), &argClass)); + return !varTypeIsLong(JITtype2varType(corType)); + } + + return !varTypeIsLong(retType); #else return true; #endif @@ -609,9 +646,10 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, // This intrinsic is supported if // - the ISA is available on the underlying hardware (compSupports returns true) // - the compiler supports this hardware intrinsics (compSupportsHWIntrinsic returns true) - // - intrinsics do not require 64-bit registers (r64) on 32-bit platforms (isTypeSupportedForIntrinsic returns + // - intrinsics do not require 64-bit registers (r64) on 32-bit platforms (signatureTypeSupproted returns // true) - bool issupported = compSupports(isa) && compSupportsHWIntrinsic(isa) && isTypeSupportedForIntrinsic(retType); + bool issupported = + compSupports(isa) && compSupportsHWIntrinsic(isa) && hwIntrinsicSignatureTypeSupported(retType, sig, flags); if (category == HW_Category_IsSupportedProperty) { @@ -656,17 +694,25 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, bool isTableDriven = impIsTableDrivenHWIntrinsic(category, flags); - if (isTableDriven && (!varTypeIsSIMD(retType) || ((flags & HW_Flag_BaseTypeFromArg) != 0))) + if (isTableDriven && ((category == HW_Category_MemoryStore) || + ((flags & (HW_Flag_BaseTypeFromFirstArg | HW_Flag_BaseTypeFromSecondArg)) != 0))) { - if (retType != TYP_VOID) + if ((flags & HW_Flag_BaseTypeFromFirstArg) != 0) { baseType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args)); } else { - assert(category == HW_Category_MemoryStore); - baseType = - getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, info.compCompHnd->getArgNext(sig->args))); + assert((category == HW_Category_MemoryStore) || ((flags & HW_Flag_BaseTypeFromSecondArg) != 0)); + CORINFO_ARG_LIST_HANDLE secondArg = info.compCompHnd->getArgNext(sig->args); + CORINFO_CLASS_HANDLE secondArgClass = info.compCompHnd->getArgClass(sig, secondArg); + baseType = getBaseTypeOfSIMDType(secondArgClass); + + if (baseType == TYP_UNKNOWN) // the second argument is not a vector + { + baseType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, secondArg, &secondArgClass))); + assert(baseType != TYP_STRUCT); + } } assert(baseType != TYP_UNKNOWN); @@ -769,10 +815,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, return impSSEIntrinsic(intrinsic, method, sig, mustExpand); case InstructionSet_SSE2: return impSSE2Intrinsic(intrinsic, method, sig, mustExpand); - case InstructionSet_SSE3: - return impSSE3Intrinsic(intrinsic, method, sig, mustExpand); - case InstructionSet_SSSE3: - return impSSSE3Intrinsic(intrinsic, method, sig, mustExpand); case InstructionSet_SSE41: return impSSE41Intrinsic(intrinsic, method, sig, mustExpand); case InstructionSet_SSE42: @@ -837,30 +879,6 @@ GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic, break; } - case NI_SSE_ConvertScalarToVector128Single: - { - assert(sig->numArgs == 2); - assert(getBaseTypeOfSIMDType(sig->retTypeSigClass) == TYP_FLOAT); - -#ifdef _TARGET_X86_ - CORINFO_CLASS_HANDLE argClass; - - CORINFO_ARG_LIST_HANDLE argLst = info.compCompHnd->getArgNext(sig->args); - CorInfoType corType = - strip(info.compCompHnd->getArgType(sig, argLst, &argClass)); // type of the second argument - - if (varTypeIsLong(JITtype2varType(corType))) - { - return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand); - } -#endif // _TARGET_X86_ - - op2 = impPopStack().val; - op1 = impSIMDPopStack(TYP_SIMD16); - retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, intrinsic, TYP_FLOAT, simdSize); - break; - } - case NI_SSE_ReciprocalScalar: case NI_SSE_ReciprocalSqrtScalar: case NI_SSE_SqrtScalar: @@ -959,88 +977,6 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, break; } - case NI_SSE2_ConvertScalarToVector128Double: - { - assert(sig->numArgs == 2); - assert(getBaseTypeOfSIMDType(sig->retTypeSigClass) == TYP_DOUBLE); - - argList = info.compCompHnd->getArgNext(sig->args); - CorInfoType corType = - strip(info.compCompHnd->getArgType(sig, argList, &argClass)); // type of the second argument - - baseType = JITtype2varType(corType); - -#ifdef _TARGET_X86_ - if (varTypeIsLong(JITtype2varType(corType))) - { - return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand); - } -#endif // _TARGET_X86_ - - if (baseType == TYP_STRUCT) - { - baseType = TYP_FLOAT; // it is the only type passed as Vector - op2 = impSIMDPopStack(TYP_SIMD16); - } - else - { - op2 = impPopStack().val; - } - - op1 = impSIMDPopStack(TYP_SIMD16); - retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, intrinsic, baseType, simdSize); - - break; - } - - case NI_SSE2_ConvertScalarToVector128Int64: - case NI_SSE2_ConvertScalarToVector128UInt64: - { - assert(sig->numArgs == 1); - baseType = getBaseTypeOfSIMDType(sig->retTypeSigClass); - assert(baseType == TYP_LONG || baseType == TYP_ULONG); - -#ifdef _TARGET_X86_ - return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand); -#endif // _TARGET_X86_ - - op1 = impPopStack().val; - retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, intrinsic, baseType, simdSize); - break; - } - - case NI_SSE2_ConvertScalarToVector128Single: - { - assert(sig->numArgs == 2); - assert(getBaseTypeOfSIMDType(sig->retTypeSigClass) == TYP_FLOAT); - - op2 = impSIMDPopStack(TYP_SIMD16); - op1 = impSIMDPopStack(TYP_SIMD16); - retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, intrinsic, TYP_DOUBLE, simdSize); - break; - } - - case NI_SSE2_ConvertToInt32: - case NI_SSE2_ConvertToInt64: - { - assert(sig->numArgs == 1); - op1 = impSIMDPopStack(TYP_SIMD16); - retType = JITtype2varType(sig->retType); - baseType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args)); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize); - break; - } - - case NI_SSE2_ConvertToUInt32: - case NI_SSE2_ConvertToUInt64: - { - assert(sig->numArgs == 1); - op1 = impSIMDPopStack(TYP_SIMD16); - baseType = JITtype2varType(sig->retType); - retNode = gtNewSimdHWIntrinsicNode(baseType, op1, intrinsic, baseType, simdSize); - break; - } - case NI_SSE2_LoadFence: case NI_SSE2_MemoryFence: { @@ -1070,22 +1006,6 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, return retNode; } -GenTree* Compiler::impSSE3Intrinsic(NamedIntrinsic intrinsic, - CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig, - bool mustExpand) -{ - return nullptr; -} - -GenTree* Compiler::impSSSE3Intrinsic(NamedIntrinsic intrinsic, - CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig, - bool mustExpand) -{ - return nullptr; -} - GenTree* Compiler::impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, diff --git a/src/jit/instrsxarch.h b/src/jit/instrsxarch.h index ddd03ddb74..d448afc977 100644 --- a/src/jit/instrsxarch.h +++ b/src/jit/instrsxarch.h @@ -452,6 +452,13 @@ INST3( movsldup, "movsldup" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SS INST3( movshdup, "movshdup" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSEFLT(0x16)) // Replicate odd-indexed Single FP Values INST3( phminposuw, "phminposuw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x41)) // Packed Horizontal Word Minimum INST3( mpsadbw, "mpsadbw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x42)) // Compute Multiple Packed Sums of Absolute Difference +INST3( pinsrb, "pinsrb" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x20)) // Insert Byte +INST3( pinsrd, "pinsrd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x22)) // Insert Dword +INST3( pinsrq, "pinsrq" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x22)) // Insert Qword +INST3( pextrb, "pextrb" , 0, IUM_WR, 0, 0, SSE3A(0x14), BAD_CODE, BAD_CODE) // Extract Byte +INST3( pextrd, "pextrd" , 0, IUM_WR, 0, 0, SSE3A(0x16), BAD_CODE, BAD_CODE) // Extract Dword +INST3( pextrq, "pextrq" , 0, IUM_WR, 0, 0, SSE3A(0x16), BAD_CODE, BAD_CODE) // Extract Qword +INST3( extractps, "extractps" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x17)) // Extract Packed Floating-Point Values INST3(LAST_SSE4_INSTRUCTION, "LAST_SSE4_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, BAD_CODE) diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp index d56abed3cc..fdb875a827 100644 --- a/src/jit/lsraxarch.cpp +++ b/src/jit/lsraxarch.cpp @@ -2255,6 +2255,7 @@ void LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) { TreeNodeInfo* info = currentNodeInfo; NamedIntrinsic intrinsicID = intrinsicTree->gtHWIntrinsicId; + var_types baseType = intrinsicTree->gtSIMDBaseType; InstructionSet isa = Compiler::isaOfHWIntrinsic(intrinsicID); HWIntrinsicCategory category = Compiler::categoryOfHWIntrinsic(intrinsicID); HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(intrinsicID); @@ -2390,6 +2391,19 @@ void LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) break; } + case NI_SSE41_Extract: + if (baseType == TYP_FLOAT) + { + info->internalIntCount += 1; + } +#ifdef _TARGET_X86_ + else if (varTypeIsByte(baseType)) + { + info->setDstCandidates(this, RBM_BYTE_REGS); + } +#endif + break; + #ifdef _TARGET_X86_ case NI_SSE42_Crc32: { diff --git a/src/jit/namedintrinsiclist.h b/src/jit/namedintrinsiclist.h index 7ad997ead7..91c9720580 100644 --- a/src/jit/namedintrinsiclist.h +++ b/src/jit/namedintrinsiclist.h @@ -75,8 +75,8 @@ enum HWIntrinsicFlag : unsigned int // some SIMD scalar intrinsics need the semantics of copying upper bits from the source operand HW_Flag_CopyUpperBits = 0x200, - // Select base type using argument type - HW_Flag_BaseTypeFromArg = 0x400, + // Select base type using the first argument type + HW_Flag_BaseTypeFromFirstArg = 0x400, // Indicates compFloatingPointUsed does not need to be set. HW_Flag_NoFloatingPointUsed = 0x800, @@ -89,9 +89,22 @@ enum HWIntrinsicFlag : unsigned int // the imm intrinsic does not need jumptable fallback when it gets non-const argument HW_Flag_NoJmpTableIMM = 0x2000, + // 64-bit intrinsics + // Intrinsics that operate over 64-bit general purpose registers are not supported on 32-bit platform + HW_Flag_64BitOnly = 0x4000, + HW_Flag_SecondArgMaybe64Bit = 0x8000, + + // Select base type using the second argument type + HW_Flag_BaseTypeFromSecondArg = 0x10000, + + // Specail codegen + // the intrinsics need special rules in CodeGen, + // but can be table-driven in the front-end + HW_Flag_SpecialCodeGen = 0x20000, + // No Read/Modify/Write Semantics - // the intrinsic does not have read/modify/write semantics and doesn't need - HW_Flag_NoRMWSemantics = 0x4000, + // the intrinsic doesn't have read/modify/write semantics in two/three-operand form. + HW_Flag_NoRMWSemantics = 0x40000, }; inline HWIntrinsicFlag operator|(HWIntrinsicFlag c1, HWIntrinsicFlag c2) diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template new file mode 100644 index 0000000000..fae1d35fb1 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{{ + public static partial class Program + {{ + private static void {2}{4}{7}() + {{ + var test = new SimpleUnaryOpTest__{2}{4}{7}(); + + try + {{ + if (test.IsSupported) + {{ + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({1}.IsSupported) + {{ + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + }} + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if ({1}.IsSupported) + {{ + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + }} + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if ({1}.IsSupported) + {{ + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + }} + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + }} + else + {{ + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + }} + }} + catch (PlatformNotSupportedException) + {{ + test.Succeeded = true; + }} + + if (!test.Succeeded) + {{ + throw new Exception("One or more scenarios did not complete as expected."); + }} + }} + }} + + public sealed unsafe class SimpleUnaryOpTest__{2}{4}{7} + {{ + private const int VectorSize = {8}; + + private const int Op1ElementCount = VectorSize / sizeof({6}); + private const int RetElementCount = VectorSize / sizeof({4}); + + private static {6}[] _data = new {6}[Op1ElementCount]; + + private static {5}<{6}> _clsVar; + + private {5}<{6}> _fld; + + private SimpleUnaryOpTest__DataTable<{4}, {6}> _dataTable; + + static SimpleUnaryOpTest__{2}{4}{7}() + {{ + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {9}; }} + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _clsVar), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize); + }} + + public SimpleUnaryOpTest__{2}{4}{7}() + {{ + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {9}; }} + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _fld), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {9}; }} + _dataTable = new SimpleUnaryOpTest__DataTable<{4}, {6}>(_data, new {4}[RetElementCount], VectorSize); + }} + + public bool IsSupported => {0}.IsSupported; + + public bool Succeeded {{ get; set; }} + + public void RunBasicScenario_UnsafeRead() + {{ + var result = {0}.{2}( + Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr), + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunBasicScenario_Load() + {{ + var result = {0}.{2}( + {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)), + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunBasicScenario_LoadAligned() + {{ + var result = {0}.{2}( + {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)), + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunReflectionScenario_UnsafeRead() + {{ + var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof(byte) }}) + .Invoke(null, new object[] {{ + Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr), + (byte){7} + }}); + + Unsafe.Write(_dataTable.outArrayPtr, ({4})(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunReflectionScenario_Load() + {{ + var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof(byte) }}) + .Invoke(null, new object[] {{ + {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)), + (byte){7} + }}); + + Unsafe.Write(_dataTable.outArrayPtr, ({4})(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunReflectionScenario_LoadAligned() + {{ + var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof(byte) }}) + .Invoke(null, new object[] {{ + {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)), + (byte){7} + }}); + + Unsafe.Write(_dataTable.outArrayPtr, ({4})(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunClsVarScenario() + {{ + var result = {0}.{2}( + _clsVar, + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + }} + + public void RunLclVarScenario_UnsafeRead() + {{ + var firstOp = Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr); + var result = {0}.{2}(firstOp, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + }} + + public void RunLclVarScenario_Load() + {{ + var firstOp = {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)); + var result = {0}.{2}(firstOp, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + }} + + public void RunLclVarScenario_LoadAligned() + {{ + var firstOp = {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)); + var result = {0}.{2}(firstOp, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + }} + + public void RunLclFldScenario() + {{ + var test = new SimpleUnaryOpTest__{2}{4}{7}(); + var result = {0}.{2}(test._fld, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + }} + + public void RunFldScenario() + {{ + var result = {0}.{2}(_fld, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + }} + + public void RunUnsupportedScenario() + {{ + Succeeded = false; + + try + {{ + RunBasicScenario_UnsafeRead(); + }} + catch (PlatformNotSupportedException) + {{ + Succeeded = true; + }} + }} + + private void ValidateResult({5}<{6}> firstOp, void* result, [CallerMemberName] string method = "") + {{ + {6}[] inArray = new {6}[Op1ElementCount]; + {4}[] outArray = new {4}[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + }} + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + {{ + {6}[] inArray = new {6}[Op1ElementCount]; + {4}[] outArray = new {4}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{6}, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + }} + + private void ValidateResult({6}[] firstOp, {4}[] result, [CallerMemberName] string method = "") + {{ + if ({10}) + {{ + Succeeded = false; + }} + + if (!Succeeded) + {{ + Console.WriteLine($"{{nameof({0})}}.{{nameof({0}.{2})}}<{4}>({5}<{6}><9>): {{method}} failed:"); + Console.WriteLine($" firstOp: ({{string.Join(", ", firstOp)}})"); + Console.WriteLine($" result: ({{string.Join(", ", result)}})"); + Console.WriteLine(); + }} + }} + }} +}} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx index 6192d9e879..cdd9ba23bd 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx @@ -211,6 +211,14 @@ private static readonly (string templateFileName, string[] templateData)[] Sse2I ("ImmUnOpTest.template", new string[] { "Sse2", "Sse2", "ShiftRightLogical128BitLane", "Vector128", "UInt32", "Vector128", "UInt32", "1", "16", "(uint)8", "result[0] != 134217728", "(i == 3 ? result[i] != 0 : result[i] != 134217728)"}), ("ImmUnOpTest.template", new string[] { "Sse2", "Sse2", "ShiftRightLogical128BitLane", "Vector128", "Int64", "Vector128", "Int64", "1", "16", "(long)8", "result[0] != 576460752303423488L", "(result[i] != 0)"}), ("ImmUnOpTest.template", new string[] { "Sse2", "Sse2", "ShiftRightLogical128BitLane", "Vector128", "UInt64", "Vector128", "UInt64", "1", "16", "(ulong)8", "result[0] != 576460752303423488UL", "(result[i] != 0)"}), + ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "Int16", "Vector128", "Int16", "1", "16", "(short)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "UInt16", "Vector128", "UInt16", "1", "16", "(ushort)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "Int16", "Vector128", "Int16", "129", "16", "(short)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "UInt16", "Vector128", "UInt16", "129", "16", "(ushort)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "Int16", "Vector128", "Int16", "1", "(short)2", "16", "(short)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "UInt16", "Vector128", "UInt16", "1", "(ushort)2","16", "(ushort)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "Int16", "Vector128", "Int16", "129","(short)2", "16", "(short)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "UInt16", "Vector128", "UInt16", "129","(ushort)2","16", "(ushort)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), }; private static readonly (string templateFileName, string[] templateData)[] Sse3Inputs = new [] @@ -339,6 +347,36 @@ private static readonly (string templateFileName, string[] templateData)[] Sse41 ("BooleanBinOpTest.template", new string[] { "Sse41", "Sse2", "TestZ", "Vector128", "UInt16", "Vector128", "UInt16", "Vector128", "UInt16", "16", "(ushort)(random.Next(0, ushort.MaxValue))", "(ushort)(random.Next(0, ushort.MaxValue))", "(left[i] & right[i]) == 0"}), ("BooleanBinOpTest.template", new string[] { "Sse41", "Sse2", "TestZ", "Vector128", "UInt32", "Vector128", "UInt32", "Vector128", "UInt32", "16", "(uint)(random.Next(0, int.MaxValue))", "(uint)(random.Next(0, int.MaxValue))", "(left[i] & right[i]) == 0"}), ("BooleanBinOpTest.template", new string[] { "Sse41", "Sse2", "TestZ", "Vector128", "UInt64", "Vector128", "UInt64", "Vector128", "UInt64", "16", "(ulong)(random.Next(0, int.MaxValue))", "(ulong)(random.Next(0, int.MaxValue))", "(left[i] & right[i]) == 0"}), + // IMM intrinsics + // TemplateName Isa, LoadIsa, Method, RetVectorType, RetBaseType, Op1VectorType, Op1BaseType, IMM, Op2 VectorSize, NextValueOp1, ValidateResults + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Byte", "Vector128", "Byte", "1", "16", "(byte)(random.Next(0, byte.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "SByte", "Vector128", "SByte", "1", "16", "(sbyte)(random.Next(0, sbyte.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int32", "Vector128", "Int32", "1", "16", "(int)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt32", "Vector128", "UInt32", "1", "16", "(uint)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int64", "Vector128", "Int64", "1", "16", "(long)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt64", "Vector128", "UInt64", "1", "16", "(ulong)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse", "Extract", "Vector128", "Single", "Vector128", "Single", "1", "16", "(float)(random.NextDouble())", "(BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1]))"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Byte", "Vector128", "Byte", "129", "16", "(byte)(random.Next(0, byte.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "SByte", "Vector128", "SByte", "129", "16", "(sbyte)(random.Next(0, sbyte.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int32", "Vector128", "Int32", "129", "16", "(int)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt32", "Vector128", "UInt32", "129", "16", "(uint)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int64", "Vector128", "Int64", "129", "16", "(long)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt64", "Vector128", "UInt64", "129", "16", "(ulong)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}), + ("ExtractScalarTest.template",new string[] { "Sse41", "Sse", "Extract", "Vector128", "Single", "Vector128", "Single", "129", "16", "(float)(random.NextDouble())", "(BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1]))"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Byte", "Vector128", "Byte", "1", "(byte)2", "16", "(byte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "SByte", "Vector128", "SByte", "1", "(sbyte)2", "16", "(sbyte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int32", "Vector128", "Int32", "1", "(int)2", "16", "(int)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt32", "Vector128", "UInt32", "1", "(uint)2", "16", "(uint)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int64", "Vector128", "Int64", "1", "(long)2", "16", "(long)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt64", "Vector128", "UInt64", "1", "(ulong)2", "16", "(ulong)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse", "Insert", "Vector128", "Single", "Vector128", "Single", "0", "(float)2", "16", "(float)0", "(i == 0 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)2) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0))"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Byte", "Vector128", "Byte", "129", "(byte)2", "16", "(byte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "SByte", "Vector128", "SByte", "129", "(sbyte)2", "16", "(sbyte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int32", "Vector128", "Int32", "129", "(int)2", "16", "(int)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt32", "Vector128", "UInt32", "129", "(uint)2", "16", "(uint)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int64", "Vector128", "Int64", "129", "(long)2", "16", "(long)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt64", "Vector128", "UInt64", "129", "(ulong)2", "16", "(ulong)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}), + ("InsertScalarTest.template",new string[] { "Sse41", "Sse", "Insert", "Vector128", "Single", "Vector128", "Single", "217", "(float)2", "16", "(float)(random.NextDouble())", "(i == 2 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0))"}), }; private static readonly (string templateFileName, string[] templateData)[] Sse42Inputs = new [] @@ -568,7 +606,8 @@ namespace JIT.HardwareIntrinsics.X86 private static bool isImmTemplate(string name) { - return name == "ImmUnOpTest.template"; + return name == "ImmUnOpTest.template" || name == "InsertScalarTest.template" || + name == "ExtractScalarTest.template"; } private static void ProcessInput(StreamWriter testListFile, (string templateFileName, string[] templateData) input) diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template new file mode 100644 index 0000000000..987a2dd6ac --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{{ + public static partial class Program + {{ + private static void {2}{4}{7}() + {{ + var test = new SimpleUnaryOpTest__{2}{4}{7}(); + + try + {{ + if (test.IsSupported) + {{ + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({1}.IsSupported) + {{ + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + }} + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if ({1}.IsSupported) + {{ + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + }} + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if ({1}.IsSupported) + {{ + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + }} + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + }} + else + {{ + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + }} + }} + catch (PlatformNotSupportedException) + {{ + test.Succeeded = true; + }} + + if (!test.Succeeded) + {{ + throw new Exception("One or more scenarios did not complete as expected."); + }} + }} + }} + + public sealed unsafe class SimpleUnaryOpTest__{2}{4}{7} + {{ + private const int VectorSize = {9}; + + private const int Op1ElementCount = VectorSize / sizeof({6}); + private const int RetElementCount = VectorSize / sizeof({4}); + + private static {6}[] _data = new {6}[Op1ElementCount]; + + private static {5}<{6}> _clsVar; + + private {5}<{6}> _fld; + + private SimpleUnaryOpTest__DataTable<{4}, {6}> _dataTable; + + static SimpleUnaryOpTest__{2}{4}{7}() + {{ + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {10}; }} + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _clsVar), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize); + }} + + public SimpleUnaryOpTest__{2}{4}{7}() + {{ + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {10}; }} + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _fld), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {10}; }} + _dataTable = new SimpleUnaryOpTest__DataTable<{4}, {6}>(_data, new {4}[RetElementCount], VectorSize); + }} + + public bool IsSupported => {0}.IsSupported; + + public bool Succeeded {{ get; set; }} + + public void RunBasicScenario_UnsafeRead() + {{ + var result = {0}.{2}( + Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr), + {8}, + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunBasicScenario_Load() + {{ + var result = {0}.{2}( + {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)), + {8}, + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunBasicScenario_LoadAligned() + {{ + var result = {0}.{2}( + {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)), + {8}, + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunReflectionScenario_UnsafeRead() + {{ + var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof({4}), typeof(byte) }}) + .Invoke(null, new object[] {{ + Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr), + {8}, + (byte){7} + }}); + + Unsafe.Write(_dataTable.outArrayPtr, ({3}<{4}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunReflectionScenario_Load() + {{ + var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof({4}), typeof(byte) }}) + .Invoke(null, new object[] {{ + {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)), + {8}, + (byte){7} + }}); + + Unsafe.Write(_dataTable.outArrayPtr, ({3}<{4}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunReflectionScenario_LoadAligned() + {{ + var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof({4}), typeof(byte) }}) + .Invoke(null, new object[] {{ + {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)), + {8}, + (byte){7} + }}); + + Unsafe.Write(_dataTable.outArrayPtr, ({3}<{4}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + }} + + public void RunClsVarScenario() + {{ + var result = {0}.{2}( + _clsVar, + {8}, + {7} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + }} + + public void RunLclVarScenario_UnsafeRead() + {{ + var firstOp = Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr); + var result = {0}.{2}(firstOp, {8}, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + }} + + public void RunLclVarScenario_Load() + {{ + var firstOp = {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)); + var result = {0}.{2}(firstOp, {8}, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + }} + + public void RunLclVarScenario_LoadAligned() + {{ + var firstOp = {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)); + var result = {0}.{2}(firstOp, {8}, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + }} + + public void RunLclFldScenario() + {{ + var test = new SimpleUnaryOpTest__{2}{4}{7}(); + var result = {0}.{2}(test._fld, {8}, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + }} + + public void RunFldScenario() + {{ + var result = {0}.{2}(_fld, {8}, {7}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + }} + + public void RunUnsupportedScenario() + {{ + Succeeded = false; + + try + {{ + RunBasicScenario_UnsafeRead(); + }} + catch (PlatformNotSupportedException) + {{ + Succeeded = true; + }} + }} + + private void ValidateResult({5}<{6}> firstOp, void* result, [CallerMemberName] string method = "") + {{ + {6}[] inArray = new {6}[Op1ElementCount]; + {4}[] outArray = new {4}[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + }} + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + {{ + {6}[] inArray = new {6}[Op1ElementCount]; + {4}[] outArray = new {4}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{6}, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + }} + + private void ValidateResult({6}[] firstOp, {4}[] result, [CallerMemberName] string method = "") + {{ + + for (var i = 0; i < RetElementCount; i++) + {{ + if ({11}) + {{ + Succeeded = false; + break; + }} + }} + + if (!Succeeded) + {{ + Console.WriteLine($"{{nameof({0})}}.{{nameof({0}.{2})}}<{4}>({5}<{6}><9>): {{method}} failed:"); + Console.WriteLine($" firstOp: ({{string.Join(", ", firstOp)}})"); + Console.WriteLine($" result: ({{string.Join(", ", result)}})"); + Console.WriteLine(); + }} + }} + }} +}} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs new file mode 100644 index 0000000000..3b3c5e1ab5 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractInt161() + { + var test = new SimpleUnaryOpTest__ExtractInt161(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractInt161 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int RetElementCount = VectorSize / sizeof(Int16); + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128<Int16> _clsVar; + + private Vector128<Int16> _fld; + + private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable; + + static SimpleUnaryOpTest__ExtractInt161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractInt161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Extract( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Extract( + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Extract( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr); + var result = Sse2.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractInt161(); + var result = Sse2.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<Int16>(Vector128<Int16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs new file mode 100644 index 0000000000..3a450f7922 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractInt16129() + { + var test = new SimpleUnaryOpTest__ExtractInt16129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractInt16129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int RetElementCount = VectorSize / sizeof(Int16); + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128<Int16> _clsVar; + + private Vector128<Int16> _fld; + + private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable; + + static SimpleUnaryOpTest__ExtractInt16129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractInt16129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Extract( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Extract( + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Extract( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr); + var result = Sse2.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractInt16129(); + var result = Sse2.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<Int16>(Vector128<Int16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs new file mode 100644 index 0000000000..24487a2dbb --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractUInt161() + { + var test = new SimpleUnaryOpTest__ExtractUInt161(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractUInt161 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int RetElementCount = VectorSize / sizeof(UInt16); + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128<UInt16> _clsVar; + + private Vector128<UInt16> _fld; + + private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable; + + static SimpleUnaryOpTest__ExtractUInt161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractUInt161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Extract( + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Extract( + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Extract( + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr); + var result = Sse2.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractUInt161(); + var result = Sse2.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<UInt16>(Vector128<UInt16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs new file mode 100644 index 0000000000..facafddf76 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractUInt16129() + { + var test = new SimpleUnaryOpTest__ExtractUInt16129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractUInt16129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int RetElementCount = VectorSize / sizeof(UInt16); + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128<UInt16> _clsVar; + + private Vector128<UInt16> _fld; + + private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable; + + static SimpleUnaryOpTest__ExtractUInt16129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractUInt16129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Extract( + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Extract( + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Extract( + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr); + var result = Sse2.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractUInt16129(); + var result = Sse2.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<UInt16>(Vector128<UInt16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs new file mode 100644 index 0000000000..90d8edb9a6 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertInt161() + { + var test = new SimpleUnaryOpTest__InsertInt161(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertInt161 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int RetElementCount = VectorSize / sizeof(Int16); + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128<Int16> _clsVar; + + private Vector128<Int16> _fld; + + private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable; + + static SimpleUnaryOpTest__InsertInt161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertInt161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Insert( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + (short)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Insert( + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Insert( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + (short)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Insert( + _clsVar, + (short)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr); + var result = Sse2.Insert(firstOp, (short)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (short)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (short)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertInt161(); + var result = Sse2.Insert(test._fld, (short)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Insert(_fld, (short)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<Int16>(Vector128<Int16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs new file mode 100644 index 0000000000..d488389ec3 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertInt16129() + { + var test = new SimpleUnaryOpTest__InsertInt16129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertInt16129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int RetElementCount = VectorSize / sizeof(Int16); + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128<Int16> _clsVar; + + private Vector128<Int16> _fld; + + private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable; + + static SimpleUnaryOpTest__InsertInt16129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertInt16129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Insert( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + (short)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Insert( + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Insert( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr), + (short)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)), + (short)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Insert( + _clsVar, + (short)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr); + var result = Sse2.Insert(firstOp, (short)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (short)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (short)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertInt16129(); + var result = Sse2.Insert(test._fld, (short)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Insert(_fld, (short)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<Int16>(Vector128<Int16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs new file mode 100644 index 0000000000..3f5b2704bd --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertUInt161() + { + var test = new SimpleUnaryOpTest__InsertUInt161(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertUInt161 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int RetElementCount = VectorSize / sizeof(UInt16); + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128<UInt16> _clsVar; + + private Vector128<UInt16> _fld; + + private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable; + + static SimpleUnaryOpTest__InsertUInt161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertUInt161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Insert( + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + (ushort)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Insert( + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Insert( + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + (ushort)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Insert( + _clsVar, + (ushort)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr); + var result = Sse2.Insert(firstOp, (ushort)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (ushort)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (ushort)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertUInt161(); + var result = Sse2.Insert(test._fld, (ushort)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Insert(_fld, (ushort)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<UInt16>(Vector128<UInt16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs new file mode 100644 index 0000000000..09e4c6933d --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertUInt16129() + { + var test = new SimpleUnaryOpTest__InsertUInt16129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertUInt16129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int RetElementCount = VectorSize / sizeof(UInt16); + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128<UInt16> _clsVar; + + private Vector128<UInt16> _fld; + + private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable; + + static SimpleUnaryOpTest__InsertUInt16129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertUInt16129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse2.Insert( + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + (ushort)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse2.Insert( + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse2.Insert( + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr), + (ushort)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)), + (ushort)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse2.Insert( + _clsVar, + (ushort)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr); + var result = Sse2.Insert(firstOp, (ushort)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (ushort)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = Sse2.Insert(firstOp, (ushort)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertUInt16129(); + var result = Sse2.Insert(test._fld, (ushort)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse2.Insert(_fld, (ushort)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<UInt16>(Vector128<UInt16><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs index bbb1468b25..ec23caaa3a 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs @@ -142,6 +142,14 @@ namespace JIT.HardwareIntrinsics.X86 ["ShiftRightLogical128BitLane.UInt32.1"] = ShiftRightLogical128BitLaneUInt321, ["ShiftRightLogical128BitLane.Int64.1"] = ShiftRightLogical128BitLaneInt641, ["ShiftRightLogical128BitLane.UInt64.1"] = ShiftRightLogical128BitLaneUInt641, + ["Extract.Int16.1"] = ExtractInt161, + ["Extract.UInt16.1"] = ExtractUInt161, + ["Extract.Int16.129"] = ExtractInt16129, + ["Extract.UInt16.129"] = ExtractUInt16129, + ["Insert.Int16.1"] = InsertInt161, + ["Insert.UInt16.1"] = InsertUInt161, + ["Insert.Int16.129"] = InsertInt16129, + ["Insert.UInt16.129"] = InsertUInt16129, }; } } diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj index d217e01700..22b99ef26f 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj @@ -79,6 +79,14 @@ <Compile Include="CompareOrdered.Double.cs" /> <Compile Include="CompareUnordered.Double.cs" /> <Compile Include="Divide.Double.cs" /> + <Compile Include="Extract.Int16.1.cs" /> + <Compile Include="Extract.UInt16.1.cs" /> + <Compile Include="Extract.Int16.129.cs" /> + <Compile Include="Extract.UInt16.129.cs" /> + <Compile Include="Insert.Int16.1.cs" /> + <Compile Include="Insert.UInt16.1.cs" /> + <Compile Include="Insert.Int16.129.cs" /> + <Compile Include="Insert.UInt16.129.cs" /> <Compile Include="Max.Double.cs" /> <Compile Include="Max.Byte.cs" /> <Compile Include="Max.Int16.cs" /> diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj index ece9047856..6d96ca6eef 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj @@ -79,6 +79,14 @@ <Compile Include="CompareOrdered.Double.cs" /> <Compile Include="CompareUnordered.Double.cs" /> <Compile Include="Divide.Double.cs" /> + <Compile Include="Extract.Int16.1.cs" /> + <Compile Include="Extract.UInt16.1.cs" /> + <Compile Include="Extract.Int16.129.cs" /> + <Compile Include="Extract.UInt16.129.cs" /> + <Compile Include="Insert.Int16.1.cs" /> + <Compile Include="Insert.UInt16.1.cs" /> + <Compile Include="Insert.Int16.129.cs" /> + <Compile Include="Insert.UInt16.129.cs" /> <Compile Include="Max.Double.cs" /> <Compile Include="Max.Byte.cs" /> <Compile Include="Max.Int16.cs" /> diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs new file mode 100644 index 0000000000..e5583d322b --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractByte1() + { + var test = new SimpleUnaryOpTest__ExtractByte1(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractByte1 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int RetElementCount = VectorSize / sizeof(Byte); + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128<Byte> _clsVar; + + private Vector128<Byte> _fld; + + private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable; + + static SimpleUnaryOpTest__ExtractByte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractByte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractByte1(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Byte>(Vector128<Byte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs new file mode 100644 index 0000000000..9b2072b925 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractByte129() + { + var test = new SimpleUnaryOpTest__ExtractByte129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractByte129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int RetElementCount = VectorSize / sizeof(Byte); + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128<Byte> _clsVar; + + private Vector128<Byte> _fld; + + private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable; + + static SimpleUnaryOpTest__ExtractByte129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractByte129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractByte129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Byte>(Vector128<Byte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs new file mode 100644 index 0000000000..5635609eb4 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractInt321() + { + var test = new SimpleUnaryOpTest__ExtractInt321(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractInt321 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int RetElementCount = VectorSize / sizeof(Int32); + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128<Int32> _clsVar; + + private Vector128<Int32> _fld; + + private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable; + + static SimpleUnaryOpTest__ExtractInt321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractInt321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractInt321(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int32>(Vector128<Int32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs new file mode 100644 index 0000000000..c1e0f4500e --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractInt32129() + { + var test = new SimpleUnaryOpTest__ExtractInt32129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractInt32129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int RetElementCount = VectorSize / sizeof(Int32); + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128<Int32> _clsVar; + + private Vector128<Int32> _fld; + + private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable; + + static SimpleUnaryOpTest__ExtractInt32129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractInt32129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractInt32129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int32>(Vector128<Int32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs new file mode 100644 index 0000000000..4f4fb7d109 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractInt641() + { + var test = new SimpleUnaryOpTest__ExtractInt641(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractInt641 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int RetElementCount = VectorSize / sizeof(Int64); + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128<Int64> _clsVar; + + private Vector128<Int64> _fld; + + private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable; + + static SimpleUnaryOpTest__ExtractInt641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractInt641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractInt641(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int64>(Vector128<Int64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs new file mode 100644 index 0000000000..15a11cb65e --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractInt64129() + { + var test = new SimpleUnaryOpTest__ExtractInt64129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractInt64129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int RetElementCount = VectorSize / sizeof(Int64); + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128<Int64> _clsVar; + + private Vector128<Int64> _fld; + + private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable; + + static SimpleUnaryOpTest__ExtractInt64129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractInt64129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractInt64129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int64>(Vector128<Int64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs new file mode 100644 index 0000000000..73bd616b67 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractSByte1() + { + var test = new SimpleUnaryOpTest__ExtractSByte1(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractSByte1 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int RetElementCount = VectorSize / sizeof(SByte); + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128<SByte> _clsVar; + + private Vector128<SByte> _fld; + + private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable; + + static SimpleUnaryOpTest__ExtractSByte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractSByte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractSByte1(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<SByte>(Vector128<SByte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs new file mode 100644 index 0000000000..219bdc47ab --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractSByte129() + { + var test = new SimpleUnaryOpTest__ExtractSByte129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractSByte129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int RetElementCount = VectorSize / sizeof(SByte); + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128<SByte> _clsVar; + + private Vector128<SByte> _fld; + + private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable; + + static SimpleUnaryOpTest__ExtractSByte129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractSByte129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractSByte129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<SByte>(Vector128<SByte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs new file mode 100644 index 0000000000..4315fda964 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractSingle1() + { + var test = new SimpleUnaryOpTest__ExtractSingle1(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractSingle1 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int RetElementCount = VectorSize / sizeof(Single); + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector128<Single> _clsVar; + + private Vector128<Single> _fld; + + private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable; + + static SimpleUnaryOpTest__ExtractSingle1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractSingle1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Single)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Single)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Single)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractSingle1(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + if ((BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1]))) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Single>(Vector128<Single><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs new file mode 100644 index 0000000000..78b40d049c --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractSingle129() + { + var test = new SimpleUnaryOpTest__ExtractSingle129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractSingle129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int RetElementCount = VectorSize / sizeof(Single); + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector128<Single> _clsVar; + + private Vector128<Single> _fld; + + private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable; + + static SimpleUnaryOpTest__ExtractSingle129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractSingle129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Single)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Single)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Single)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractSingle129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + if ((BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1]))) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Single>(Vector128<Single><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs new file mode 100644 index 0000000000..1545207481 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractUInt321() + { + var test = new SimpleUnaryOpTest__ExtractUInt321(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractUInt321 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int RetElementCount = VectorSize / sizeof(UInt32); + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128<UInt32> _clsVar; + + private Vector128<UInt32> _fld; + + private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable; + + static SimpleUnaryOpTest__ExtractUInt321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractUInt321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractUInt321(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt32>(Vector128<UInt32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs new file mode 100644 index 0000000000..3d38f36744 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractUInt32129() + { + var test = new SimpleUnaryOpTest__ExtractUInt32129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractUInt32129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int RetElementCount = VectorSize / sizeof(UInt32); + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128<UInt32> _clsVar; + + private Vector128<UInt32> _fld; + + private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable; + + static SimpleUnaryOpTest__ExtractUInt32129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractUInt32129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractUInt32129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt32>(Vector128<UInt32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs new file mode 100644 index 0000000000..f7e3300162 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractUInt641() + { + var test = new SimpleUnaryOpTest__ExtractUInt641(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractUInt641 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int RetElementCount = VectorSize / sizeof(UInt64); + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128<UInt64> _clsVar; + + private Vector128<UInt64> _fld; + + private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable; + + static SimpleUnaryOpTest__ExtractUInt641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractUInt641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractUInt641(); + var result = Sse41.Extract(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt64>(Vector128<UInt64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs new file mode 100644 index 0000000000..53d42020da --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void ExtractUInt64129() + { + var test = new SimpleUnaryOpTest__ExtractUInt64129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ExtractUInt64129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int RetElementCount = VectorSize / sizeof(UInt64); + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128<UInt64> _clsVar; + + private Vector128<UInt64> _fld; + + private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable; + + static SimpleUnaryOpTest__ExtractUInt64129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractUInt64129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Extract( + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Extract( + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Extract( + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Extract( + _clsVar, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Extract(firstOp, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractUInt64129(); + var result = Sse41.Extract(test._fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Extract(_fld, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + if ((result[0] != firstOp[1])) + { + Succeeded = false; + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt64>(Vector128<UInt64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs new file mode 100644 index 0000000000..173d44e91f --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertByte1() + { + var test = new SimpleUnaryOpTest__InsertByte1(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertByte1 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int RetElementCount = VectorSize / sizeof(Byte); + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128<Byte> _clsVar; + + private Vector128<Byte> _fld; + + private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable; + + static SimpleUnaryOpTest__InsertByte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertByte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + (byte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + (byte)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (byte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (byte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (byte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (byte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertByte1(); + var result = Sse41.Insert(test._fld, (byte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (byte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Byte>(Vector128<Byte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs new file mode 100644 index 0000000000..26d0b8ab47 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertByte129() + { + var test = new SimpleUnaryOpTest__InsertByte129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertByte129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int RetElementCount = VectorSize / sizeof(Byte); + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128<Byte> _clsVar; + + private Vector128<Byte> _fld; + + private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable; + + static SimpleUnaryOpTest__InsertByte129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertByte129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + (byte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr), + (byte)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (byte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (byte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (byte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (byte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertByte129(); + var result = Sse41.Insert(test._fld, (byte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (byte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Byte>(Vector128<Byte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs new file mode 100644 index 0000000000..404cbb56a0 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertInt321() + { + var test = new SimpleUnaryOpTest__InsertInt321(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertInt321 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int RetElementCount = VectorSize / sizeof(Int32); + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128<Int32> _clsVar; + + private Vector128<Int32> _fld; + + private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable; + + static SimpleUnaryOpTest__InsertInt321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertInt321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + (int)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + (int)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (int)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (int)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (int)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (int)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertInt321(); + var result = Sse41.Insert(test._fld, (int)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (int)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int32>(Vector128<Int32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs new file mode 100644 index 0000000000..d5d09c4d04 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertInt32129() + { + var test = new SimpleUnaryOpTest__InsertInt32129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertInt32129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int RetElementCount = VectorSize / sizeof(Int32); + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128<Int32> _clsVar; + + private Vector128<Int32> _fld; + + private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable; + + static SimpleUnaryOpTest__InsertInt32129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertInt32129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + (int)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr), + (int)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)), + (int)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (int)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (int)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (int)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (int)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertInt32129(); + var result = Sse41.Insert(test._fld, (int)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (int)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int32>(Vector128<Int32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs new file mode 100644 index 0000000000..ff48f25b03 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertInt641() + { + var test = new SimpleUnaryOpTest__InsertInt641(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertInt641 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int RetElementCount = VectorSize / sizeof(Int64); + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128<Int64> _clsVar; + + private Vector128<Int64> _fld; + + private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable; + + static SimpleUnaryOpTest__InsertInt641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertInt641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + (long)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + (long)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (long)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (long)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (long)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (long)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertInt641(); + var result = Sse41.Insert(test._fld, (long)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (long)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int64>(Vector128<Int64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs new file mode 100644 index 0000000000..ff396b3fe1 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertInt64129() + { + var test = new SimpleUnaryOpTest__InsertInt64129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertInt64129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int RetElementCount = VectorSize / sizeof(Int64); + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128<Int64> _clsVar; + + private Vector128<Int64> _fld; + + private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable; + + static SimpleUnaryOpTest__InsertInt64129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertInt64129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + (long)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr), + (long)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)), + (long)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (long)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (long)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (long)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (long)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertInt64129(); + var result = Sse41.Insert(test._fld, (long)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (long)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int64>(Vector128<Int64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs new file mode 100644 index 0000000000..bec049220f --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertSByte1() + { + var test = new SimpleUnaryOpTest__InsertSByte1(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertSByte1 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int RetElementCount = VectorSize / sizeof(SByte); + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128<SByte> _clsVar; + + private Vector128<SByte> _fld; + + private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable; + + static SimpleUnaryOpTest__InsertSByte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertSByte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + (sbyte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + (sbyte)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (sbyte)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (sbyte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (sbyte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (sbyte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertSByte1(); + var result = Sse41.Insert(test._fld, (sbyte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (sbyte)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<SByte>(Vector128<SByte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs new file mode 100644 index 0000000000..d1c339b99c --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertSByte129() + { + var test = new SimpleUnaryOpTest__InsertSByte129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertSByte129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int RetElementCount = VectorSize / sizeof(SByte); + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128<SByte> _clsVar; + + private Vector128<SByte> _fld; + + private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable; + + static SimpleUnaryOpTest__InsertSByte129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertSByte129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + (sbyte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr), + (sbyte)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)), + (sbyte)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (sbyte)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (sbyte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (sbyte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (sbyte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertSByte129(); + var result = Sse41.Insert(test._fld, (sbyte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (sbyte)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<SByte>(Vector128<SByte><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs new file mode 100644 index 0000000000..294fb0ecb9 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertSingle0() + { + var test = new SimpleUnaryOpTest__InsertSingle0(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertSingle0 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int RetElementCount = VectorSize / sizeof(Single); + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector128<Single> _clsVar; + + private Vector128<Single> _fld; + + private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable; + + static SimpleUnaryOpTest__InsertSingle0() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertSingle0() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + (float)2, + 0 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + 0 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + 0 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + (float)2, + (byte)0 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + (byte)0 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + (byte)0 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (float)2, + 0 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (float)2, 0); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (float)2, 0); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (float)2, 0); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertSingle0(); + var result = Sse41.Insert(test._fld, (float)2, 0); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (float)2, 0); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 0 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)2) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0))) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Single>(Vector128<Single><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs new file mode 100644 index 0000000000..7b3fcc762c --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertSingle217() + { + var test = new SimpleUnaryOpTest__InsertSingle217(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertSingle217 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int RetElementCount = VectorSize / sizeof(Single); + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector128<Single> _clsVar; + + private Vector128<Single> _fld; + + private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable; + + static SimpleUnaryOpTest__InsertSingle217() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertSingle217() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + (float)2, + 217 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + 217 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + 217 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr), + (float)2, + (byte)217 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + (byte)217 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) }) + .Invoke(null, new object[] { + Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)), + (float)2, + (byte)217 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (float)2, + 217 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (float)2, 217); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (float)2, 217); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (float)2, 217); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertSingle217(); + var result = Sse41.Insert(test._fld, (float)2, 217); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (float)2, 217); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 2 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0))) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Single>(Vector128<Single><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs new file mode 100644 index 0000000000..4568cc8916 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertUInt321() + { + var test = new SimpleUnaryOpTest__InsertUInt321(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertUInt321 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int RetElementCount = VectorSize / sizeof(UInt32); + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128<UInt32> _clsVar; + + private Vector128<UInt32> _fld; + + private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable; + + static SimpleUnaryOpTest__InsertUInt321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertUInt321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + (uint)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + (uint)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (uint)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (uint)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (uint)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (uint)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertUInt321(); + var result = Sse41.Insert(test._fld, (uint)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (uint)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt32>(Vector128<UInt32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs new file mode 100644 index 0000000000..060909cbfe --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertUInt32129() + { + var test = new SimpleUnaryOpTest__InsertUInt32129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertUInt32129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int RetElementCount = VectorSize / sizeof(UInt32); + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128<UInt32> _clsVar; + + private Vector128<UInt32> _fld; + + private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable; + + static SimpleUnaryOpTest__InsertUInt32129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertUInt32129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + (uint)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr), + (uint)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)), + (uint)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (uint)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (uint)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (uint)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (uint)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertUInt32129(); + var result = Sse41.Insert(test._fld, (uint)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (uint)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt32>(Vector128<UInt32><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs new file mode 100644 index 0000000000..966c3ab247 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertUInt641() + { + var test = new SimpleUnaryOpTest__InsertUInt641(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertUInt641 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int RetElementCount = VectorSize / sizeof(UInt64); + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128<UInt64> _clsVar; + + private Vector128<UInt64> _fld; + + private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable; + + static SimpleUnaryOpTest__InsertUInt641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertUInt641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + (ulong)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + (ulong)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (ulong)2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (ulong)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (ulong)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (ulong)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertUInt641(); + var result = Sse41.Insert(test._fld, (ulong)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (ulong)2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt64>(Vector128<UInt64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs new file mode 100644 index 0000000000..2ad20b9637 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * 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; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertUInt64129() + { + var test = new SimpleUnaryOpTest__InsertUInt64129(); + + try + { + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + } + catch (PlatformNotSupportedException) + { + test.Succeeded = true; + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__InsertUInt64129 + { + private const int VectorSize = 16; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int RetElementCount = VectorSize / sizeof(UInt64); + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128<UInt64> _clsVar; + + private Vector128<UInt64> _fld; + + private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable; + + static SimpleUnaryOpTest__InsertUInt64129() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__InsertUInt64129() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; } + _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Sse41.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Sse41.Insert( + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + (ulong)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Sse41.Insert( + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Sse41.Insert( + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr), + (ulong)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)), + (ulong)2, + (byte)129 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Sse41.Insert( + _clsVar, + (ulong)2, + 129 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr); + var result = Sse41.Insert(firstOp, (ulong)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (ulong)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = Sse41.Insert(firstOp, (ulong)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__InsertUInt64129(); + var result = Sse41.Insert(test._fld, (ulong)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Sse41.Insert(_fld, (ulong)2, 129); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + + for (var i = 0; i < RetElementCount; i++) + { + if ((i == 1 ? result[i] != 2 : result[i] != 0)) + { + Succeeded = false; + break; + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt64>(Vector128<UInt64><9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs index c941543373..6e56c9f2f4 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs @@ -104,6 +104,34 @@ namespace JIT.HardwareIntrinsics.X86 ["TestZ.UInt16"] = TestZUInt16, ["TestZ.UInt32"] = TestZUInt32, ["TestZ.UInt64"] = TestZUInt64, + ["Extract.Byte.1"] = ExtractByte1, + ["Extract.SByte.1"] = ExtractSByte1, + ["Extract.Int32.1"] = ExtractInt321, + ["Extract.UInt32.1"] = ExtractUInt321, + ["Extract.Int64.1"] = ExtractInt641, + ["Extract.UInt64.1"] = ExtractUInt641, + ["Extract.Single.1"] = ExtractSingle1, + ["Extract.Byte.129"] = ExtractByte129, + ["Extract.SByte.129"] = ExtractSByte129, + ["Extract.Int32.129"] = ExtractInt32129, + ["Extract.UInt32.129"] = ExtractUInt32129, + ["Extract.Int64.129"] = ExtractInt64129, + ["Extract.UInt64.129"] = ExtractUInt64129, + ["Extract.Single.129"] = ExtractSingle129, + ["Insert.Byte.1"] = InsertByte1, + ["Insert.SByte.1"] = InsertSByte1, + ["Insert.Int32.1"] = InsertInt321, + ["Insert.UInt32.1"] = InsertUInt321, + ["Insert.Int64.1"] = InsertInt641, + ["Insert.UInt64.1"] = InsertUInt641, + ["Insert.Single.0"] = InsertSingle0, + ["Insert.Byte.129"] = InsertByte129, + ["Insert.SByte.129"] = InsertSByte129, + ["Insert.Int32.129"] = InsertInt32129, + ["Insert.UInt32.129"] = InsertUInt32129, + ["Insert.Int64.129"] = InsertInt64129, + ["Insert.UInt64.129"] = InsertUInt64129, + ["Insert.Single.217"] = InsertSingle217, }; } } diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj index 158e94a27d..12a6b0b10d 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj @@ -119,6 +119,34 @@ <Compile Include="TestZ.UInt16.cs" /> <Compile Include="TestZ.UInt32.cs" /> <Compile Include="TestZ.UInt64.cs" /> + <Compile Include="Extract.Byte.1.cs" /> + <Compile Include="Extract.SByte.1.cs" /> + <Compile Include="Extract.Int32.1.cs" /> + <Compile Include="Extract.UInt32.1.cs" /> + <Compile Include="Extract.Int64.1.cs" /> + <Compile Include="Extract.UInt64.1.cs" /> + <Compile Include="Extract.Single.1.cs" /> + <Compile Include="Extract.Byte.129.cs" /> + <Compile Include="Extract.SByte.129.cs" /> + <Compile Include="Extract.Int32.129.cs" /> + <Compile Include="Extract.UInt32.129.cs" /> + <Compile Include="Extract.Int64.129.cs" /> + <Compile Include="Extract.UInt64.129.cs" /> + <Compile Include="Extract.Single.129.cs" /> + <Compile Include="Insert.Byte.1.cs" /> + <Compile Include="Insert.SByte.1.cs" /> + <Compile Include="Insert.Int32.1.cs" /> + <Compile Include="Insert.UInt32.1.cs" /> + <Compile Include="Insert.Int64.1.cs" /> + <Compile Include="Insert.UInt64.1.cs" /> + <Compile Include="Insert.Single.0.cs" /> + <Compile Include="Insert.Byte.129.cs" /> + <Compile Include="Insert.SByte.129.cs" /> + <Compile Include="Insert.Int32.129.cs" /> + <Compile Include="Insert.UInt32.129.cs" /> + <Compile Include="Insert.Int64.129.cs" /> + <Compile Include="Insert.UInt64.129.cs" /> + <Compile Include="Insert.Single.217.cs" /> <Compile Include="Program.Sse41.cs" /> <Compile Include="..\Shared\BooleanUnOpTest_DataTable.cs" /> <Compile Include="..\Shared\BooleanBinOpTest_DataTable.cs" /> diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj index 74dcfa091e..de6d56ed7e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj @@ -119,6 +119,34 @@ <Compile Include="TestZ.UInt16.cs" /> <Compile Include="TestZ.UInt32.cs" /> <Compile Include="TestZ.UInt64.cs" /> + <Compile Include="Extract.Byte.1.cs" /> + <Compile Include="Extract.SByte.1.cs" /> + <Compile Include="Extract.Int32.1.cs" /> + <Compile Include="Extract.UInt32.1.cs" /> + <Compile Include="Extract.Int64.1.cs" /> + <Compile Include="Extract.UInt64.1.cs" /> + <Compile Include="Extract.Single.1.cs" /> + <Compile Include="Extract.Byte.129.cs" /> + <Compile Include="Extract.SByte.129.cs" /> + <Compile Include="Extract.Int32.129.cs" /> + <Compile Include="Extract.UInt32.129.cs" /> + <Compile Include="Extract.Int64.129.cs" /> + <Compile Include="Extract.UInt64.129.cs" /> + <Compile Include="Extract.Single.129.cs" /> + <Compile Include="Insert.Byte.1.cs" /> + <Compile Include="Insert.SByte.1.cs" /> + <Compile Include="Insert.Int32.1.cs" /> + <Compile Include="Insert.UInt32.1.cs" /> + <Compile Include="Insert.Int64.1.cs" /> + <Compile Include="Insert.UInt64.1.cs" /> + <Compile Include="Insert.Single.0.cs" /> + <Compile Include="Insert.Byte.129.cs" /> + <Compile Include="Insert.SByte.129.cs" /> + <Compile Include="Insert.Int32.129.cs" /> + <Compile Include="Insert.UInt32.129.cs" /> + <Compile Include="Insert.Int64.129.cs" /> + <Compile Include="Insert.UInt64.129.cs" /> + <Compile Include="Insert.Single.217.cs" /> <Compile Include="Program.Sse41.cs" /> <Compile Include="..\Shared\BooleanUnOpTest_DataTable.cs" /> <Compile Include="..\Shared\BooleanBinOpTest_DataTable.cs" /> |