diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 5f51bd68e138db..c8ecb1d1279106 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -9084,6 +9084,8 @@ class Compiler return isSIMDClass(clsHnd) || isHWSIMDClass(clsHnd); } + var_types getSIMDType(CORINFO_CLASS_HANDLE typeHnd, CorInfoType* baseType = nullptr); + // Get the base (element) type and size in bytes for a SIMD type. Returns CORINFO_TYPE_UNDEF // if it is not a SIMD type or is an unsupported base JIT type. CorInfoType getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, unsigned* sizeBytes = nullptr); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index b9d49d5655f500..ea8dd6586aff3b 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -20962,7 +20962,7 @@ GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types ty GenTree* Compiler::gtNewSimdAbsNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeGet() == type); @@ -21055,7 +21055,7 @@ GenTree* Compiler::gtNewSimdBinOpNode( genTreeOps op, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); @@ -21769,7 +21769,7 @@ GenTree* Compiler::gtNewSimdBinOpNode( GenTree* Compiler::gtNewSimdCeilNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -21849,7 +21849,7 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -21985,7 +21985,7 @@ GenTree* Compiler::gtNewSimdCvtNativeNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -22237,7 +22237,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( genTreeOps op, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -22526,12 +22526,11 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode( genTreeOps op, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { assert(type == TYP_INT); + assert(op1 != nullptr); - var_types simdType = getSIMDTypeForSize(simdSize); + var_types simdType = op1->TypeGet(); assert(varTypeIsSIMD(simdType)); - - assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); + assert(genTypeSize(simdType) == simdSize); assert(op2 != nullptr); assert(op2->TypeIs(simdType)); @@ -22661,11 +22660,10 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode( { assert(type == TYP_INT); - var_types simdType = getSIMDTypeForSize(simdSize); - assert(varTypeIsSIMD(simdType)); - assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); + var_types simdType = op1->TypeGet(); + assert(varTypeIsSIMD(simdType)); + assert(genTypeSize(simdType) == simdSize); assert(op2 != nullptr); assert(op2->TypeIs(simdType)); @@ -22791,7 +22789,7 @@ GenTree* Compiler::gtNewSimdCndSelNode( var_types type, GenTree* op1, GenTree* op2, GenTree* op3, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23216,7 +23214,7 @@ GenTree* Compiler::gtNewSimdCreateSequenceNode( // is constant than there isn't any real optimization we can do and we need the full computation. assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); @@ -23387,14 +23385,14 @@ GenTree* Compiler::gtNewSimdCreateSequenceNode( GenTree* Compiler::gtNewSimdDotProdNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { - var_types simdType = getSIMDTypeForSize(simdSize); - assert(varTypeIsSIMD(simdType)); + assert(varTypeIsSIMD(type)); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); + assert(op1->TypeIs(type)); assert(op2 != nullptr); - assert(op2->TypeIs(simdType)); + assert(op2->TypeIs(type)); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsSIMD(type)); @@ -23428,7 +23426,7 @@ GenTree* Compiler::gtNewSimdDotProdNode( GenTree* Compiler::gtNewSimdFloorNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23473,7 +23471,7 @@ GenTree* Compiler::gtNewSimdFmaNode( var_types type, GenTree* op1, GenTree* op2, GenTree* op3, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23588,7 +23586,7 @@ GenTree* Compiler::gtNewSimdGetElementNode( GenTree* Compiler::gtNewSimdGetIndicesNode(var_types type, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); @@ -23741,7 +23739,7 @@ GenTree* Compiler::gtNewSimdIsEvenIntegerNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23768,7 +23766,7 @@ GenTree* Compiler::gtNewSimdIsEvenIntegerNode(var_types type, GenTree* Compiler::gtNewSimdIsFiniteNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23819,7 +23817,7 @@ GenTree* Compiler::gtNewSimdIsFiniteNode(var_types type, GenTree* op1, CorInfoTy GenTree* Compiler::gtNewSimdIsInfinityNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23850,7 +23848,7 @@ GenTree* Compiler::gtNewSimdIsInfinityNode(var_types type, GenTree* op1, CorInfo GenTree* Compiler::gtNewSimdIsIntegerNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23890,7 +23888,7 @@ GenTree* Compiler::gtNewSimdIsIntegerNode(var_types type, GenTree* op1, CorInfoT GenTree* Compiler::gtNewSimdIsNaNNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23921,7 +23919,7 @@ GenTree* Compiler::gtNewSimdIsNaNNode(var_types type, GenTree* op1, CorInfoType GenTree* Compiler::gtNewSimdIsNegativeNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -23963,7 +23961,7 @@ GenTree* Compiler::gtNewSimdIsNegativeInfinityNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24011,7 +24009,7 @@ GenTree* Compiler::gtNewSimdIsNegativeInfinityNode(var_types type, GenTree* Compiler::gtNewSimdIsNormalNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24074,7 +24072,7 @@ GenTree* Compiler::gtNewSimdIsOddIntegerNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24101,7 +24099,7 @@ GenTree* Compiler::gtNewSimdIsOddIntegerNode(var_types type, GenTree* Compiler::gtNewSimdIsPositiveNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24143,7 +24141,7 @@ GenTree* Compiler::gtNewSimdIsPositiveInfinityNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24194,7 +24192,7 @@ GenTree* Compiler::gtNewSimdIsSubnormalNode(var_types type, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24251,7 +24249,7 @@ GenTree* Compiler::gtNewSimdIsSubnormalNode(var_types type, GenTree* Compiler::gtNewSimdIsZeroNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -24277,7 +24275,7 @@ GenTree* Compiler::gtNewSimdIsZeroNode(var_types type, GenTree* op1, CorInfoType GenTree* Compiler::gtNewSimdLoadNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); @@ -24472,7 +24470,7 @@ GenTree* Compiler::gtNewSimdMinMaxNode(var_types type, else if (!varTypeIsLong(simdBaseType)) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); } NamedIntrinsic intrinsic = NI_Illegal; @@ -25114,7 +25112,7 @@ GenTree* Compiler::gtNewSimdMinMaxNativeNode( else { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); } NamedIntrinsic intrinsic = NI_Illegal; @@ -25227,7 +25225,7 @@ GenTree* Compiler::gtNewSimdNarrowNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -25699,7 +25697,7 @@ GenTree* Compiler::gtNewSimdNarrowNode( GenTree* Compiler::gtNewSimdRoundNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -25760,7 +25758,7 @@ GenTree* Compiler::gtNewSimdShuffleVariableNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize, bool isShuffleNative) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -26363,7 +26361,7 @@ GenTree* Compiler::gtNewSimdShuffleNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize, bool isShuffleNative) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -26946,7 +26944,7 @@ GenTree* Compiler::gtNewSimdShuffleNode( GenTree* Compiler::gtNewSimdSqrtNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -27004,7 +27002,7 @@ GenTree* Compiler::gtNewSimdStoreNode(GenTree* op1, GenTree* op2, CorInfoType si assert(op2 != nullptr); assert(varTypeIsSIMD(op2)); - assert(getSIMDTypeForSize(simdSize) == op2->TypeGet()); + assert(genTypeSize(op2->TypeGet()) == simdSize); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); @@ -27121,11 +27119,10 @@ GenTree* Compiler::gtNewSimdStoreNonTemporalNode(GenTree* op1, GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { - var_types simdType = getSIMDTypeForSize(simdSize); - assert(varTypeIsSIMD(simdType)); - assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); + var_types simdType = op1->TypeGet(); + assert(varTypeIsSIMD(simdType)); + assert(genTypeSize(simdType) == simdSize); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(varTypeIsArithmetic(simdBaseType)); @@ -27453,7 +27450,7 @@ GenTree* Compiler::gtNewSimdToScalarNode(var_types type, GenTree* op1, CorInfoTy GenTree* Compiler::gtNewSimdTruncNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -27498,7 +27495,7 @@ GenTree* Compiler::gtNewSimdUnOpNode( genTreeOps op, var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -27593,7 +27590,7 @@ GenTree* Compiler::gtNewSimdUnOpNode( GenTree* Compiler::gtNewSimdWidenLowerNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -27789,7 +27786,7 @@ GenTree* Compiler::gtNewSimdWidenLowerNode(var_types type, GenTree* op1, CorInfo GenTree* Compiler::gtNewSimdWidenUpperNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) { assert(varTypeIsSIMD(type)); - assert(getSIMDTypeForSize(simdSize) == type); + assert(genTypeSize(type) == simdSize); assert(op1 != nullptr); assert(op1->TypeIs(type)); @@ -28115,15 +28112,15 @@ GenTreeFieldList* Compiler::gtConvertParamOpToFieldList(GenTree* op, unsigned fi unsigned fieldSize = opVarDsc->lvExactSize() / fieldCount; GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList(); int offset = 0; - unsigned sizeBytes = 0; CORINFO_CLASS_HANDLE structType; for (unsigned fieldId = 0; fieldId < fieldCount; fieldId++) { CORINFO_FIELD_HANDLE fieldHandle = info.compCompHnd->getFieldInClass(clsHnd, fieldId); JitType2PreciseVarType(info.compCompHnd->getFieldType(fieldHandle, &structType)); - getBaseJitTypeAndSizeOfSIMDType(structType, &sizeBytes); - var_types simdType = getSIMDTypeForSize(sizeBytes); + + unsigned int size = info.compCompHnd->getClassSize(structType); + var_types simdType = getSIMDTypeForSize(size); GenTreeLclFld* fldNode = gtNewLclFldNode(lclNum, simdType, offset); fieldList->AddField(this, fldNode, offset, simdType); @@ -29663,10 +29660,8 @@ genTreeOps GenTreeHWIntrinsic::GetOperForHWIntrinsicId(NamedIntrinsic id, var_ty NamedIntrinsic GenTreeHWIntrinsic::GetHWIntrinsicIdForUnOp( Compiler* comp, genTreeOps oper, GenTree* op1, var_types simdBaseType, unsigned simdSize, bool isScalar) { - var_types simdType = comp->getSIMDTypeForSize(simdSize); assert(varTypeIsArithmetic(simdBaseType)); - assert(varTypeIsSIMD(simdType)); #if defined(TARGET_XARCH) if ((simdSize == 64) || (simdSize == 32)) @@ -29684,7 +29679,9 @@ NamedIntrinsic GenTreeHWIntrinsic::GetHWIntrinsicIdForUnOp( } assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); + var_types simdType = op1->TypeGet(); + assert(varTypeIsSIMD(simdType)); + assert(genTypeSize(simdType) == simdSize); NamedIntrinsic id = NI_Illegal; @@ -29757,13 +29754,12 @@ NamedIntrinsic GenTreeHWIntrinsic::GetHWIntrinsicIdForBinOp(Compiler* comp, unsigned simdSize, bool isScalar) { - var_types simdType = comp->getSIMDTypeForSize(simdSize); - assert(varTypeIsArithmetic(simdBaseType)); - assert(varTypeIsSIMD(simdType)); assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); + var_types simdType = op1->TypeGet(); + assert(varTypeIsSIMD(simdType)); + assert(genTypeSize(simdType) == simdSize); assert(op2 != nullptr); #if defined(TARGET_XARCH) @@ -30330,16 +30326,14 @@ NamedIntrinsic GenTreeHWIntrinsic::GetHWIntrinsicIdForCmpOp(Compiler* comp, bool isScalar, bool reverseCond) { - var_types simdType = comp->getSIMDTypeForSize(simdSize); + assert(op1 != nullptr); + assert(op2 != nullptr); + var_types simdType = op1->TypeGet(); + assert(genTypeSize(simdType) == simdSize); assert(varTypeIsMask(type) || (type == simdType)); - assert(varTypeIsArithmetic(simdBaseType)); assert(varTypeIsSIMD(simdType)); - assert(op1 != nullptr); - assert(op1->TypeIs(simdType)); - assert(op2 != nullptr); - #if defined(TARGET_XARCH) if (varTypeIsMask(type)) { @@ -30671,11 +30665,8 @@ NamedIntrinsic GenTreeHWIntrinsic::GetHWIntrinsicIdForCmpOp(Compiler* comp, var_types GenTreeHWIntrinsic::GetLookupTypeForCmpOp( Compiler* comp, genTreeOps oper, var_types type, var_types simdBaseType, unsigned simdSize, bool reverseCond) { - var_types simdType = comp->getSIMDTypeForSize(simdSize); - assert(varTypeIsMask(type) || (type == simdType)); - + assert(varTypeIsMask(type) || (varTypeIsSIMD(type) && (genTypeSize(type) == simdSize))); assert(varTypeIsArithmetic(simdBaseType)); - assert(varTypeIsSIMD(simdType)); var_types lookupType = type; @@ -32516,8 +32507,6 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) case NI_Vector512_ToScalar: #endif { - var_types simdType = getSIMDTypeForSize(simdSize); - if (varTypeIsFloating(retType)) { double result = cnsNode->AsVecCon()->ToScalarFloating(simdBaseType); @@ -32777,8 +32766,6 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) break; } - var_types simdType = getSIMDTypeForSize(simdSize); - if (varTypeIsFloating(retType)) { double result = cnsNode->AsVecCon()->GetElementFloating(simdBaseType, index); @@ -33721,8 +33708,6 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) break; } - var_types simdType = getSIMDTypeForSize(simdSize); - if (varTypeIsFloating(simdBaseType)) { double value = op3->AsDblCon()->DconValue(); diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 83909542992db3..5a4ed811abdcc1 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1502,9 +1502,7 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE { if (!varTypeIsSIMD(argType)) { - unsigned int argSizeBytes; - (void)getBaseJitTypeAndSizeOfSIMDType(argClass, &argSizeBytes); - argType = getSIMDTypeForSize(argSizeBytes); + argType = getSIMDType(argClass); } assert(varTypeIsSIMD(argType)); @@ -1889,29 +1887,20 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; GenTree* retNode = nullptr; - if (retType == TYP_STRUCT) + if (retType == TYP_STRUCT && !HWIntrinsicInfo::IsMultiReg(intrinsic)) { - unsigned int sizeBytes; - simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(sig->retTypeSigClass, &sizeBytes); - - if (HWIntrinsicInfo::IsMultiReg(intrinsic)) - { - assert(sizeBytes == 0); - } + retType = impNormStructType(sig->retTypeSigClass, &simdBaseJitType); #ifdef TARGET_ARM64 - else if ((intrinsic == NI_AdvSimd_LoadAndInsertScalar) || (intrinsic == NI_AdvSimd_Arm64_LoadAndInsertScalar)) + if ((intrinsic == NI_AdvSimd_LoadAndInsertScalar) || (intrinsic == NI_AdvSimd_Arm64_LoadAndInsertScalar)) { - CorInfoType pSimdBaseJitType = CORINFO_TYPE_UNDEF; - var_types retFieldType = impNormStructType(sig->retTypeSigClass, &pSimdBaseJitType); - - if (retFieldType == TYP_STRUCT) + if (retType == TYP_STRUCT) { CORINFO_CLASS_HANDLE structType; unsigned int sizeBytes = 0; // LoadAndInsertScalar that returns 2,3 or 4 vectors - assert(pSimdBaseJitType == CORINFO_TYPE_UNDEF); + assert(simdBaseJitType == CORINFO_TYPE_UNDEF); unsigned fieldCount = info.compCompHnd->getClassNumInstanceFields(sig->retTypeSigClass); assert(fieldCount > 1); CORINFO_FIELD_HANDLE fieldHandle = info.compCompHnd->getFieldInClass(sig->retTypeClass, 0); @@ -1937,24 +1926,20 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, } else { - assert((retFieldType == TYP_SIMD8) || (retFieldType == TYP_SIMD16)); + assert((retType == TYP_SIMD8) || (retType == TYP_SIMD16)); assert(isSupportedBaseType(intrinsic, simdBaseJitType)); - retType = getSIMDTypeForSize(sizeBytes); } } -#endif else - { +#endif // We want to return early here for cases where retType was TYP_STRUCT as per method signature and // rather than deferring the decision after getting the simdBaseJitType of arg. - if (!isSupportedBaseType(intrinsic, simdBaseJitType)) + if (retType == TYP_UNDEF || !isSupportedBaseType(intrinsic, simdBaseJitType)) { return nullptr; } - assert(sizeBytes != 0); - retType = getSIMDTypeForSize(sizeBytes); - } + assert((varTypeIsSIMD(retType) || varTypeIsStruct(retType)) && isSupportedBaseType(intrinsic, simdBaseJitType)); } simdBaseJitType = getBaseJitTypeFromArgIfNeeded(intrinsic, sig, simdBaseJitType); diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 7e73e3e2fee48c..9a89ac905074cf 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -1339,12 +1339,10 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if (!varTypeIsLong(simdBaseType)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); - retNode = gtNewSimdDotProdNode(simdType, op1, op2, simdBaseJitType, simdSize); + retNode = gtNewSimdDotProdNode(op1->TypeGet(), op1, op2, simdBaseJitType, simdSize); retNode = gtNewSimdGetElementNode(retType, retNode, gtNewIconNode(0), simdBaseJitType, simdSize); } break; diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 5d67351639e840..847c15800f9e97 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -1185,12 +1185,12 @@ var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoTyp if (structSizeMightRepresentSIMDType(originalSize)) { - unsigned int sizeBytes; - CorInfoType simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(structHnd, &sizeBytes); - if (simdBaseJitType != CORINFO_TYPE_UNDEF) + CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; + var_types simdType = getSIMDType(structHnd, &simdBaseJitType); + if (simdBaseJitType != CORINFO_TYPE_UNDEF && simdType != TYP_UNDEF) { - assert(sizeBytes == originalSize); - structType = getSIMDTypeForSize(sizeBytes); + assert(genTypeSize(simdType) == originalSize); + structType = simdType; if (pSimdBaseJitType != nullptr) { *pSimdBaseJitType = simdBaseJitType; diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 109afd011d8190..de8be1829f7f43 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1445,15 +1445,10 @@ var_types Compiler::StructPromotionHelper::TryPromoteValueClassAsPrimitive(CORIN #ifdef FEATURE_SIMD if (compiler->isRuntimeIntrinsicsNamespace(namespaceName) || compiler->isNumericsNamespace(namespaceName)) { - unsigned simdSize; - CorInfoType simdBaseJitType = compiler->getBaseJitTypeAndSizeOfSIMDType(node.simdTypeHnd, &simdSize); - // We will only promote fields of SIMD types that fit into a SIMD register. - if (simdBaseJitType != CORINFO_TYPE_UNDEF) + var_types type = compiler->getSIMDType(node.simdTypeHnd); + if (type != TYP_UNDEF) { - if (compiler->structSizeMightRepresentSIMDType(simdSize)) - { - return compiler->getSIMDTypeForSize(simdSize); - } + return type; } } #endif diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 7fdbd76afb0081..6b1ca64d38037f 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -153,32 +153,21 @@ unsigned Compiler::getFFRegisterVarNum() } #endif -//---------------------------------------------------------------------------------- -// Return the base type and size of SIMD vector type given its type handle. -// -// Arguments: -// typeHnd - The handle of the type we're interested in. -// sizeBytes - out param -// -// Return Value: -// base type of SIMD vector. -// sizeBytes if non-null is set to size in bytes. -// -// Notes: -// If the size of the struct is already known call structSizeMightRepresentSIMDType -// to determine if this api needs to be called. -// -// The type handle passed here can only be used in a subset of JIT-EE calls -// since it may be called by promotion during AOT of a method that does -// not version with SPC. See CORINFO_TYPE_LAYOUT_NODE for the contract on -// the supported JIT-EE calls. -// -// TODO-Throughput: current implementation parses class name to find base type. Change -// this when we implement SIMD intrinsic identification for the final -// product. -// -CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, unsigned* sizeBytes /*= nullptr */) +var_types Compiler::getSIMDType(CORINFO_CLASS_HANDLE typeHnd, CorInfoType* baseType) { + var_types type = TYP_UNDEF; + CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; + + if ((typeHnd == nullptr) || !isIntrinsicType(typeHnd)) + { + return TYP_UNDEF; + } + + if (baseType != nullptr) + { + *baseType = simdBaseJitType; + } + if (m_simdHandleCache == nullptr) { if (impInlineInfo == nullptr) @@ -198,23 +187,9 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH } } - if (sizeBytes != nullptr) - { - *sizeBytes = 0; - } - - if ((typeHnd == nullptr) || !isIntrinsicType(typeHnd)) - { - return CORINFO_TYPE_UNDEF; - } - const char* namespaceName; const char* className = getClassNameFromMetadata(typeHnd, &namespaceName); - // fast path search using cached type handles of important types - CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; - unsigned size = 0; - if (isNumericsNamespace(namespaceName)) { switch (className[0]) @@ -223,14 +198,14 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strcmp(className, "Plane") != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Known type Plane\n"); m_simdHandleCache->PlaneHandle = typeHnd; + type = TYP_SIMD16; simdBaseJitType = CORINFO_TYPE_FLOAT; - size = 4 * genTypeSize(TYP_FLOAT); break; } @@ -238,14 +213,14 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strcmp(className, "Quaternion") != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Known type Quaternion\n"); m_simdHandleCache->QuaternionHandle = typeHnd; + type = TYP_SIMD16; simdBaseJitType = CORINFO_TYPE_FLOAT; - size = 4 * genTypeSize(TYP_FLOAT); break; } @@ -253,7 +228,7 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strncmp(className, "Vector", 6) != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } switch (className[6]) @@ -269,14 +244,14 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (className[7] != '\0') { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector2\n"); m_simdHandleCache->Vector2Handle = typeHnd; + type = TYP_SIMD8; simdBaseJitType = CORINFO_TYPE_FLOAT; - size = 2 * genTypeSize(TYP_FLOAT); break; } @@ -284,14 +259,14 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (className[7] != '\0') { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector3\n"); m_simdHandleCache->Vector3Handle = typeHnd; + type = TYP_SIMD12; simdBaseJitType = CORINFO_TYPE_FLOAT; - size = 3 * genTypeSize(TYP_FLOAT); break; } @@ -299,14 +274,14 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (className[7] != '\0') { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector4\n"); m_simdHandleCache->Vector4Handle = typeHnd; + type = TYP_SIMD16; simdBaseJitType = CORINFO_TYPE_FLOAT; - size = 4 * genTypeSize(TYP_FLOAT); break; } @@ -314,7 +289,7 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if ((className[7] != '1') || (className[8] != '\0')) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } CORINFO_CLASS_HANDLE typeArgHnd = info.compCompHnd->getTypeInstantiationArgument(typeHnd, 0); @@ -322,22 +297,24 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH if ((simdBaseJitType < CORINFO_TYPE_BYTE) || (simdBaseJitType > CORINFO_TYPE_DOUBLE)) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector<%s>\n", varTypeName(JitType2PreciseVarType(simdBaseJitType))); - size = getVectorTByteLength(); - if (size == 0) + uint32_t vectlen = getVectorTByteLength(); + if (vectlen == 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } + + type = getSIMDTypeForSize(vectlen); break; } default: { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } } break; @@ -345,14 +322,14 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH default: { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } } } #ifdef FEATURE_HW_INTRINSICS else { - size = info.compCompHnd->getClassSize(typeHnd); + unsigned int size = info.compCompHnd->getClassSize(typeHnd); switch (size) { @@ -361,7 +338,7 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strcmp(className, "Vector64`1") != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } CORINFO_CLASS_HANDLE typeArgHnd = info.compCompHnd->getTypeInstantiationArgument(typeHnd, 0); @@ -369,10 +346,11 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH if ((simdBaseJitType < CORINFO_TYPE_BYTE) || (simdBaseJitType > CORINFO_TYPE_DOUBLE)) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector64<%s>\n", varTypeName(JitType2PreciseVarType(simdBaseJitType))); + type = TYP_SIMD8; break; } #endif // TARGET_ARM64 @@ -381,7 +359,7 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strcmp(className, "Vector128`1") != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } CORINFO_CLASS_HANDLE typeArgHnd = info.compCompHnd->getTypeInstantiationArgument(typeHnd, 0); @@ -389,10 +367,11 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH if ((simdBaseJitType < CORINFO_TYPE_BYTE) || (simdBaseJitType > CORINFO_TYPE_DOUBLE)) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector128<%s>\n", varTypeName(JitType2PreciseVarType(simdBaseJitType))); + type = TYP_SIMD16; break; } @@ -401,7 +380,7 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strcmp(className, "Vector256`1") != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } CORINFO_CLASS_HANDLE typeArgHnd = info.compCompHnd->getTypeInstantiationArgument(typeHnd, 0); @@ -409,16 +388,17 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH if ((simdBaseJitType < CORINFO_TYPE_BYTE) || (simdBaseJitType > CORINFO_TYPE_DOUBLE)) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } if (!compOpportunisticallyDependsOn(InstructionSet_AVX)) { // We must treat as a regular struct if AVX isn't supported - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector256<%s>\n", varTypeName(JitType2PreciseVarType(simdBaseJitType))); + type = TYP_SIMD32; break; } @@ -426,7 +406,7 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH { if (strcmp(className, "Vector512`1") != 0) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } CORINFO_CLASS_HANDLE typeArgHnd = info.compCompHnd->getTypeInstantiationArgument(typeHnd, 0); @@ -434,40 +414,84 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH if ((simdBaseJitType < CORINFO_TYPE_BYTE) || (simdBaseJitType > CORINFO_TYPE_DOUBLE)) { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } if (!compOpportunisticallyDependsOn(InstructionSet_AVX512)) { // We must treat as a regular struct if AVX512 isn't supported - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } JITDUMP(" Found Vector512<%s>\n", varTypeName(JitType2PreciseVarType(simdBaseJitType))); + type = TYP_SIMD64; break; } #endif // TARGET_XARCH default: { - return CORINFO_TYPE_UNDEF; + return TYP_UNDEF; } } } #endif // FEATURE_HW_INTRINSICS - if (sizeBytes != nullptr) + if (baseType != nullptr) { - *sizeBytes = size; + *baseType = simdBaseJitType; } if (simdBaseJitType != CORINFO_TYPE_UNDEF) { - assert(size == info.compCompHnd->getClassSize(typeHnd)); + assert(genTypeSize(type) == info.compCompHnd->getClassSize(typeHnd)); setUsesSIMDTypes(true); } - return simdBaseJitType; + return type; +} + +//---------------------------------------------------------------------------------- +// Return the base type and size of SIMD vector type given its type handle. +// +// Arguments: +// typeHnd - The handle of the type we're interested in. +// sizeBytes - out param +// +// Return Value: +// base type of SIMD vector. +// sizeBytes if non-null is set to size in bytes. +// +// Notes: +// If the size of the struct is already known call structSizeMightRepresentSIMDType +// to determine if this api needs to be called. +// +// The type handle passed here can only be used in a subset of JIT-EE calls +// since it may be called by promotion during AOT of a method that does +// not version with SPC. See CORINFO_TYPE_LAYOUT_NODE for the contract on +// the supported JIT-EE calls. +// +// TODO-Throughput: current implementation parses class name to find base type. Change +// this when we implement SIMD intrinsic identification for the final +// product. +// +CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, unsigned* sizeBytes /*= nullptr */) +{ + CorInfoType baseType = CORINFO_TYPE_UNDEF; + + if (sizeBytes != nullptr) + { + *sizeBytes = 0; + } + + var_types type = getSIMDType(typeHnd, &baseType); + + if (sizeBytes != nullptr && type != TYP_UNDEF) + { + *sizeBytes = genTypeSize(type); + } + + return baseType; } //------------------------------------------------------------------------