summaryrefslogtreecommitdiff
path: root/src/jit/simd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/simd.cpp')
-rw-r--r--src/jit/simd.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/jit/simd.cpp b/src/jit/simd.cpp
index 4ba7832cca..bbb9a57cc4 100644
--- a/src/jit/simd.cpp
+++ b/src/jit/simd.cpp
@@ -2609,6 +2609,10 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode,
// Unary operators that take and return a Vector.
case SIMDIntrinsicCast:
+ case SIMDIntrinsicConvertToSingle:
+ case SIMDIntrinsicConvertToDouble:
+ case SIMDIntrinsicConvertToInt32:
+ case SIMDIntrinsicConvertToUInt32:
{
op1 = impSIMDPopStack(simdType, instMethod);
@@ -2617,6 +2621,61 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode,
}
break;
+ case SIMDIntrinsicConvertToInt64:
+ case SIMDIntrinsicConvertToUInt64:
+ {
+#ifdef _TARGET_AMD64_
+ op1 = impSIMDPopStack(simdType, instMethod);
+
+ simdTree = gtNewSIMDNode(simdType, op1, nullptr, simdIntrinsicID, baseType, size);
+ retVal = simdTree;
+#else
+ JITDUMP("SIMD Conversion to Int64/UInt64 is not supported on this platform\n");
+ return nullptr;
+#endif
+ }
+ break;
+
+ case SIMDIntrinsicNarrow:
+ {
+ assert(!instMethod);
+ op2 = impSIMDPopStack(simdType);
+ op1 = impSIMDPopStack(simdType);
+ // op1 and op2 are two input Vector<T>.
+ simdTree = gtNewSIMDNode(simdType, op1, op2, simdIntrinsicID, baseType, size);
+ retVal = simdTree;
+ }
+ break;
+
+ case SIMDIntrinsicWiden:
+ {
+ GenTree* dstAddrHi = impSIMDPopStack(TYP_BYREF);
+ GenTree* dstAddrLo = impSIMDPopStack(TYP_BYREF);
+ op1 = impSIMDPopStack(simdType);
+ GenTree* dupOp1 = fgInsertCommaFormTemp(&op1, gtGetStructHandleForSIMD(simdType, baseType));
+
+ // Widen the lower half and assign it to dstAddrLo.
+ simdTree = gtNewSIMDNode(simdType, op1, nullptr, SIMDIntrinsicWidenLo, baseType, size);
+ GenTree* loDest =
+ new (this, GT_BLK) GenTreeBlk(GT_BLK, simdType, dstAddrLo, getSIMDTypeSizeInBytes(clsHnd));
+ GenTree* loAsg = gtNewBlkOpNode(loDest, simdTree, getSIMDTypeSizeInBytes(clsHnd),
+ false, // not volatile
+ true); // copyBlock
+ loAsg->gtFlags |= ((simdTree->gtFlags | dstAddrLo->gtFlags) & GTF_ALL_EFFECT);
+
+ // Widen the upper half and assign it to dstAddrHi.
+ simdTree = gtNewSIMDNode(simdType, dupOp1, nullptr, SIMDIntrinsicWidenHi, baseType, size);
+ GenTree* hiDest =
+ new (this, GT_BLK) GenTreeBlk(GT_BLK, simdType, dstAddrHi, getSIMDTypeSizeInBytes(clsHnd));
+ GenTree* hiAsg = gtNewBlkOpNode(hiDest, simdTree, getSIMDTypeSizeInBytes(clsHnd),
+ false, // not volatile
+ true); // copyBlock
+ hiAsg->gtFlags |= ((simdTree->gtFlags | dstAddrHi->gtFlags) & GTF_ALL_EFFECT);
+
+ retVal = gtNewOperNode(GT_COMMA, simdType, loAsg, hiAsg);
+ }
+ break;
+
case SIMDIntrinsicHWAccel:
{
GenTreeIntCon* intConstTree = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, 1);