diff --git a/docs/design/coreclr/jit/first-class-structs.md b/docs/design/coreclr/jit/first-class-structs.md
index d72af35753dae..dc017aee75f2e 100644
--- a/docs/design/coreclr/jit/first-class-structs.md
+++ b/docs/design/coreclr/jit/first-class-structs.md
@@ -113,9 +113,9 @@ Structs only appear as rvalues in the following contexts:
* As a call argument
* In this context, it must be one of: `GT_OBJ`, `GT_LCL_VAR`, `GT_LCL_FLD` or `GT_FIELD_LIST`.
-* As an operand to a hardware or SIMD intrinsic (for `TYP_SIMD*` only)
+* As an operand to a hardware intrinsic (for `TYP_SIMD*` only)
* In this case the struct handle is generally assumed to be unneeded, as it is captured (directly or
- indirectly) in the `GT_SIMD` or `GT_HWINTRINSIC` node.
+ indirectly) in the `GT_HWINTRINSIC` node.
* It would simplify both the recognition and optimization of these nodes if they carried a `ClassLayout`.
After morph, a struct-typed value on the RHS of assignment is one of:
@@ -124,7 +124,6 @@ After morph, a struct-typed value on the RHS of assignment is one of:
* `GT_CALL`
* `GT_LCL_VAR`
* `GT_LCL_FLD`
-* `GT_SIMD`
* `GT_OBJ` nodes can also be used as rvalues when they are call arguments
* Proposed: `GT_OBJ` nodes can be used in any context where a struct rvalue or lvalue might occur,
except after morph when the struct is independently promoted.
diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt
index 4e3640cdccfbd..b39a7316530d5 100644
--- a/src/coreclr/jit/CMakeLists.txt
+++ b/src/coreclr/jit/CMakeLists.txt
@@ -340,7 +340,6 @@ set( JIT_HEADERS
sideeffects.h
simd.h
simdashwintrinsic.h
- simdintrinsiclist.h
sm.h
smallhash.h
smcommon.h
diff --git a/src/coreclr/jit/clrjit.natvis b/src/coreclr/jit/clrjit.natvis
index 5873fca508786..b44fd31bc85ac 100644
--- a/src/coreclr/jit/clrjit.natvis
+++ b/src/coreclr/jit/clrjit.natvis
@@ -59,7 +59,6 @@ Documentation for VS debugger format specifiers: https://docs.microsoft.com/en-u
{gtTreeID, d}: [[{this->gtOp1,na}={this->gtOp2,na}]
{gtTreeID, d}: [[{((GenTreeCast*)this)->gtCastType,en} <- {((GenTreeUnOp*)this)->gtOp1->gtType,en}]
- {gtTreeID, d}: [[{((GenTreeSIMD*)this)->gtSIMDIntrinsicID,en}, {gtType,en}]
{gtTreeID, d}: [[{((GenTreeHWIntrinsic*)this)->gtHWIntrinsicId,en}, {gtType,en}]
{gtTreeID, d}: [[{gtOper,en}, {gtType,en}]
diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h
index ef14cf55bbd4c..2cf76a5cbf6a4 100644
--- a/src/coreclr/jit/codegen.h
+++ b/src/coreclr/jit/codegen.h
@@ -1058,7 +1058,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genCodeForContainedCompareChain(GenTree* tree, bool* inchain, GenCondition* prevCond);
#endif
void genCodeForSelect(GenTreeOp* select);
- void genIntrinsic(GenTree* treeNode);
+ void genIntrinsic(GenTreeIntrinsic* treeNode);
void genPutArgStk(GenTreePutArgStk* treeNode);
void genPutArgReg(GenTreeOp* tree);
#if FEATURE_ARG_SPLIT
@@ -1078,9 +1078,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#ifdef TARGET_ARM64
insOpts genGetSimdInsOpt(emitAttr size, var_types elementType);
#endif
- void genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode);
- void genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode);
- void genSIMDIntrinsic(GenTreeSIMD* simdNode);
+ void genSimdUpperSave(GenTreeIntrinsic* node);
+ void genSimdUpperRestore(GenTreeIntrinsic* node);
// TYP_SIMD12 (i.e Vector3 of size 12 bytes) is not a hardware supported size and requires
// two reads/writes on 64-bit targets. These routines abstract reading/writing of Vector3
diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp
index 0adfcc5484641..6a969c7e7cb4a 100644
--- a/src/coreclr/jit/codegenarm64.cpp
+++ b/src/coreclr/jit/codegenarm64.cpp
@@ -5018,46 +5018,6 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
}
#ifdef FEATURE_SIMD
-
-//------------------------------------------------------------------------
-// genSIMDIntrinsic: Generate code for a SIMD Intrinsic. This is the main
-// routine which in turn calls appropriate genSIMDIntrinsicXXX() routine.
-//
-// Arguments:
-// simdNode - The GT_SIMD node
-//
-// Return Value:
-// None.
-//
-// Notes:
-// Currently, we only recognize SIMDVector and SIMDVector, and
-// a limited set of methods.
-//
-// TODO-CLEANUP Merge all versions of this function and move to new file simdcodegencommon.cpp.
-void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
-{
- // NYI for unsupported base types
- if (!varTypeIsArithmetic(simdNode->GetSimdBaseType()))
- {
- noway_assert(!"SIMD intrinsic with unsupported base type.");
- }
-
- switch (simdNode->GetSIMDIntrinsicId())
- {
- case SIMDIntrinsicUpperSave:
- genSIMDIntrinsicUpperSave(simdNode);
- break;
-
- case SIMDIntrinsicUpperRestore:
- genSIMDIntrinsicUpperRestore(simdNode);
- break;
-
- default:
- noway_assert(!"Unimplemented SIMD intrinsic.");
- unreached();
- }
-}
-
insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
{
assert((size == EA_16BYTE) || (size == EA_8BYTE));
@@ -5092,11 +5052,11 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
}
//-----------------------------------------------------------------------------
-// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD16 vector to
-// the given register, if any, or to memory.
+// genSimdUpperSave: save the upper half of a TYP_SIMD16 vector to
+// the given register, if any, or to memory.
//
// Arguments:
-// simdNode - The GT_SIMD node
+// node - The GT_INTRINSIC node
//
// Return Value:
// None.
@@ -5109,81 +5069,93 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
// In that case, this node will be marked GTF_SPILL, which will cause this method to save
// the upper half to the lclVar's home location.
//
-void CodeGen::genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode)
+void CodeGen::genSimdUpperSave(GenTreeIntrinsic* node)
{
- assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicUpperSave);
+ assert(node->gtIntrinsicName == NI_SIMD_UpperSave);
+
+ GenTree* op1 = node->gtGetOp1();
+ assert(op1->IsLocal());
- GenTree* op1 = simdNode->Op(1);
GenTreeLclVar* lclNode = op1->AsLclVar();
LclVarDsc* varDsc = compiler->lvaGetDesc(lclNode);
assert(emitTypeSize(varDsc->GetRegisterType(lclNode)) == 16);
- regNumber targetReg = simdNode->GetRegNum();
- regNumber op1Reg = genConsumeReg(op1);
+ regNumber tgtReg = node->GetRegNum();
+ assert(tgtReg != REG_NA);
+
+ regNumber op1Reg = genConsumeReg(op1);
assert(op1Reg != REG_NA);
- assert(targetReg != REG_NA);
- GetEmitter()->emitIns_R_R_I_I(INS_mov, EA_8BYTE, targetReg, op1Reg, 0, 1);
- if ((simdNode->gtFlags & GTF_SPILL) != 0)
+ GetEmitter()->emitIns_R_R_I_I(INS_mov, EA_8BYTE, tgtReg, op1Reg, 0, 1);
+
+ if ((node->gtFlags & GTF_SPILL) != 0)
{
// This is not a normal spill; we'll spill it to the lclVar location.
// The localVar must have a stack home.
+
unsigned varNum = lclNode->GetLclNum();
assert(varDsc->lvOnFrame);
+
// We want to store this to the upper 8 bytes of this localVar's home.
int offset = 8;
emitAttr attr = emitTypeSize(TYP_SIMD8);
- GetEmitter()->emitIns_S_R(INS_str, attr, targetReg, varNum, offset);
+ GetEmitter()->emitIns_S_R(INS_str, attr, tgtReg, varNum, offset);
}
else
{
- genProduceReg(simdNode);
+ genProduceReg(node);
}
}
//-----------------------------------------------------------------------------
-// genSIMDIntrinsicUpperRestore: Restore the upper half of a TYP_SIMD16 vector to
-// the given register, if any, or to memory.
+// genSimdUpperRestore: Restore the upper half of a TYP_SIMD16 vector to
+// the given register, if any, or to memory.
//
// Arguments:
-// simdNode - The GT_SIMD node
+// node - The GT_INTRINSIC node
//
// Return Value:
// None.
//
// Notes:
-// For consistency with genSIMDIntrinsicUpperSave, and to ensure that lclVar nodes always
-// have their home register, this node has its targetReg on the lclVar child, and its source
-// on the simdNode.
-// Regarding spill, please see the note above on genSIMDIntrinsicUpperSave. If we have spilled
+// For consistency with genSimdUpperSave, and to ensure that lclVar nodes always
+// have their home register, this node has its tgtReg on the lclVar child, and its source
+// on the node.
+// Regarding spill, please see the note above on genSimdUpperSave. If we have spilled
// an upper-half to the lclVar's home location, this node will be marked GTF_SPILLED.
//
-void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
+void CodeGen::genSimdUpperRestore(GenTreeIntrinsic* node)
{
- assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicUpperRestore);
+ assert(node->gtIntrinsicName == NI_SIMD_UpperRestore);
- GenTree* op1 = simdNode->Op(1);
+ GenTree* op1 = node->gtGetOp1();
assert(op1->IsLocal());
+
GenTreeLclVar* lclNode = op1->AsLclVar();
LclVarDsc* varDsc = compiler->lvaGetDesc(lclNode);
assert(emitTypeSize(varDsc->GetRegisterType(lclNode)) == 16);
- regNumber srcReg = simdNode->GetRegNum();
+ regNumber srcReg = node->GetRegNum();
+ assert(srcReg != REG_NA);
+
regNumber lclVarReg = genConsumeReg(lclNode);
- unsigned varNum = lclNode->GetLclNum();
assert(lclVarReg != REG_NA);
- assert(srcReg != REG_NA);
- if (simdNode->gtFlags & GTF_SPILLED)
+
+ unsigned varNum = lclNode->GetLclNum();
+
+ if (node->gtFlags & GTF_SPILLED)
{
// The localVar must have a stack home.
assert(varDsc->lvOnFrame);
+
// We will load this from the upper 8 bytes of this localVar's home.
int offset = 8;
emitAttr attr = emitTypeSize(TYP_SIMD8);
GetEmitter()->emitIns_R_S(INS_ldr, attr, srcReg, varNum, offset);
}
+
GetEmitter()->emitIns_R_R_I_I(INS_mov, EA_8BYTE, lclVarReg, srcReg, 1, 0);
}
diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp
index 9fa3560730719..3bf17cee35156 100644
--- a/src/coreclr/jit/codegenarmarch.cpp
+++ b/src/coreclr/jit/codegenarmarch.cpp
@@ -334,15 +334,9 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
break;
case GT_INTRINSIC:
- genIntrinsic(treeNode);
+ genIntrinsic(treeNode->AsIntrinsic());
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- genSIMDIntrinsic(treeNode->AsSIMD());
- break;
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
genHWIntrinsic(treeNode->AsHWIntrinsic());
@@ -662,18 +656,21 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg)
// Return value:
// None
//
-void CodeGen::genIntrinsic(GenTree* treeNode)
+void CodeGen::genIntrinsic(GenTreeIntrinsic* treeNode)
{
- assert(treeNode->OperIs(GT_INTRINSIC));
-
// Both operand and its result must be of the same floating point type.
- GenTree* srcNode = treeNode->AsOp()->gtOp1;
- assert(varTypeIsFloating(srcNode));
- assert(srcNode->TypeGet() == treeNode->TypeGet());
+ GenTree* srcNode = treeNode->gtGetOp1();
- // Only a subset of functions are treated as math intrinsics.
- //
- switch (treeNode->AsIntrinsic()->gtIntrinsicName)
+#ifdef DEBUG
+ if ((treeNode->gtIntrinsicName > NI_SYSTEM_MATH_START) && (treeNode->gtIntrinsicName < NI_SYSTEM_MATH_END))
+ {
+ assert(varTypeIsFloating(srcNode));
+ assert(srcNode->TypeGet() == treeNode->TypeGet());
+ }
+#endif // DEBUG
+
+ // Handle intrinsics that can be implemented by target-specific instructions
+ switch (treeNode->gtIntrinsicName)
{
case NI_System_Math_Abs:
genConsumeOperands(treeNode->AsOp());
@@ -704,13 +701,13 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
case NI_System_Math_Max:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitIns_R_R_R(INS_fmax, emitActualTypeSize(treeNode), treeNode->GetRegNum(),
- treeNode->gtGetOp1()->GetRegNum(), treeNode->gtGetOp2()->GetRegNum());
+ srcNode->GetRegNum(), treeNode->gtGetOp2()->GetRegNum());
break;
case NI_System_Math_Min:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitIns_R_R_R(INS_fmin, emitActualTypeSize(treeNode), treeNode->GetRegNum(),
- treeNode->gtGetOp1()->GetRegNum(), treeNode->gtGetOp2()->GetRegNum());
+ srcNode->GetRegNum(), treeNode->gtGetOp2()->GetRegNum());
break;
#endif // TARGET_ARM64
@@ -719,6 +716,23 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
GetEmitter()->emitInsBinary(INS_SQRT, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
+#if defined(FEATURE_SIMD)
+ // The handling is a bit more complex so genSimdUpperSave/Restore
+ // handles genConsumeOperands and genProduceReg
+
+ case NI_SIMD_UpperRestore:
+ {
+ genSimdUpperRestore(treeNode);
+ return;
+ }
+
+ case NI_SIMD_UpperSave:
+ {
+ genSimdUpperSave(treeNode);
+ return;
+ }
+#endif // FEATURE_SIMD
+
default:
assert(!"genIntrinsic: Unsupported intrinsic");
unreached();
diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp
index d7f3c66dbe6b2..dc5e7dffbe44a 100644
--- a/src/coreclr/jit/codegenlinear.cpp
+++ b/src/coreclr/jit/codegenlinear.cpp
@@ -1717,7 +1717,7 @@ void CodeGen::genConsumeOperands(GenTreeOp* tree)
#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
//------------------------------------------------------------------------
// genConsumeOperands: Do liveness update for the operands of a multi-operand node,
-// currently GT_SIMD or GT_HWINTRINSIC
+// currently GT_HWINTRINSIC
//
// Arguments:
// tree - the GenTreeMultiOp whose operands will have their liveness updated.
diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp
index 298d17e9e4cbf..e17dd3d743377 100644
--- a/src/coreclr/jit/codegenloongarch64.cpp
+++ b/src/coreclr/jit/codegenloongarch64.cpp
@@ -4855,27 +4855,6 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
}
#ifdef FEATURE_SIMD
-
-//------------------------------------------------------------------------
-// genSIMDIntrinsic: Generate code for a SIMD Intrinsic. This is the main
-// routine which in turn calls appropriate genSIMDIntrinsicXXX() routine.
-//
-// Arguments:
-// simdNode - The GT_SIMD node
-//
-// Return Value:
-// None.
-//
-// Notes:
-// Currently, we only recognize SIMDVector and SIMDVector, and
-// a limited set of methods.
-//
-// TODO-CLEANUP Merge all versions of this function and move to new file simdcodegencommon.cpp.
-void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
-{
- NYI("unimplemented on LOONGARCH64 yet");
-}
-
insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
{
NYI("unimplemented on LOONGARCH64 yet");
@@ -4883,11 +4862,11 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
}
//-----------------------------------------------------------------------------
-// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD16 vector to
-// the given register, if any, or to memory.
+// genSimdUpperSave: save the upper half of a TYP_SIMD16 vector to
+// the given register, if any, or to memory.
//
// Arguments:
-// simdNode - The GT_SIMD node
+// node - The GT_INTRINSIC node
//
// Return Value:
// None.
@@ -4900,29 +4879,29 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
// In that case, this node will be marked GTF_SPILL, which will cause this method to save
// the upper half to the lclVar's home location.
//
-void CodeGen::genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode)
+void CodeGen::genSimdUpperSave(GenTreeIntrinsic* node)
{
NYI("unimplemented on LOONGARCH64 yet");
}
//-----------------------------------------------------------------------------
-// genSIMDIntrinsicUpperRestore: Restore the upper half of a TYP_SIMD16 vector to
-// the given register, if any, or to memory.
+// genSimdUpperRestore: Restore the upper half of a TYP_SIMD16 vector to
+// the given register, if any, or to memory.
//
// Arguments:
-// simdNode - The GT_SIMD node
+// node - The GT_INTRINSIC node
//
// Return Value:
// None.
//
// Notes:
-// For consistency with genSIMDIntrinsicUpperSave, and to ensure that lclVar nodes always
-// have their home register, this node has its targetReg on the lclVar child, and its source
-// on the simdNode.
-// Regarding spill, please see the note above on genSIMDIntrinsicUpperSave. If we have spilled
+// For consistency with genSimdUpperSave, and to ensure that lclVar nodes always
+// have their home register, this node has its tgtReg on the lclVar child, and its source
+// on the node.
+// Regarding spill, please see the note above on genSimdUpperSave. If we have spilled
// an upper-half to the lclVar's home location, this node will be marked GTF_SPILLED.
//
-void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
+void CodeGen::genSimdUpperRestore(GenTreeIntrinsic* node)
{
NYI("unimplemented on LOONGARCH64 yet");
}
@@ -5299,12 +5278,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
genIntrinsic(treeNode);
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- genSIMDIntrinsic(treeNode->AsSIMD());
- break;
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
genHWIntrinsic(treeNode->AsHWIntrinsic());
diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp
index b838a387440cc..6780ab666212a 100644
--- a/src/coreclr/jit/codegenxarch.cpp
+++ b/src/coreclr/jit/codegenxarch.cpp
@@ -1743,15 +1743,9 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
break;
case GT_INTRINSIC:
- genIntrinsic(treeNode);
+ genIntrinsic(treeNode->AsIntrinsic());
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- genSIMDIntrinsic(treeNode->AsSIMD());
- break;
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
genHWIntrinsic(treeNode->AsHWIntrinsic());
@@ -7657,10 +7651,10 @@ void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode)
// Return value:
// None
//
-void CodeGen::genIntrinsic(GenTree* treeNode)
+void CodeGen::genIntrinsic(GenTreeIntrinsic* treeNode)
{
// Handle intrinsics that can be implemented by target-specific instructions
- switch (treeNode->AsIntrinsic()->gtIntrinsicName)
+ switch (treeNode->gtIntrinsicName)
{
case NI_System_Math_Abs:
genSSE2BitwiseOp(treeNode);
@@ -7676,7 +7670,7 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
case NI_System_Math_Sqrt:
{
// Both operand and its result must be of the same floating point type.
- GenTree* srcNode = treeNode->AsOp()->gtOp1;
+ GenTree* srcNode = treeNode->gtGetOp1();
assert(varTypeIsFloating(srcNode));
assert(srcNode->TypeGet() == treeNode->TypeGet());
@@ -7687,6 +7681,23 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
break;
}
+#if defined(FEATURE_SIMD)
+ // The handling is a bit more complex so genSimdUpperSave/Restore
+ // handles genConsumeOperands and genProduceReg
+
+ case NI_SIMD_UpperRestore:
+ {
+ genSimdUpperRestore(treeNode);
+ return;
+ }
+
+ case NI_SIMD_UpperSave:
+ {
+ genSimdUpperSave(treeNode);
+ return;
+ }
+#endif // FEATURE_SIMD
+
default:
assert(!"genIntrinsic: Unsupported intrinsic");
unreached();
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index b771b4ceba10c..69d29c74d1894 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -2390,14 +2390,6 @@ class Compiler
genTreeOps oper, GenTree* cond, GenTree* op1, GenTree* op2, var_types type);
#ifdef FEATURE_SIMD
- GenTreeSIMD* gtNewSIMDNode(
- var_types type, GenTree* op1, SIMDIntrinsicID simdIntrinsicID, CorInfoType simdBaseJitType, unsigned simdSize);
- GenTreeSIMD* gtNewSIMDNode(var_types type,
- GenTree* op1,
- GenTree* op2,
- SIMDIntrinsicID simdIntrinsicID,
- CorInfoType simdBaseJitType,
- unsigned simdSize);
void SetOpLclRelatedToSIMDIntrinsic(GenTree* op);
#endif
@@ -4884,11 +4876,6 @@ class Compiler
void fgValueNumberArrIndexAddr(GenTreeArrAddr* arrAddr);
-#ifdef FEATURE_SIMD
- // Does value-numbering for a GT_SIMD tree
- void fgValueNumberSimd(GenTreeSIMD* tree);
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
// Does value-numbering for a GT_HWINTRINSIC tree
void fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree);
@@ -8585,32 +8572,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
bool areArgumentsContiguous(GenTree* op1, GenTree* op2);
GenTree* CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_types simdBaseType, unsigned simdSize);
- // Whether SIMD vector occupies part of SIMD register.
- // SSE2: vector2f/3f are considered sub register SIMD types.
- // AVX: vector2f, 3f and 4f are all considered sub register SIMD types.
- bool isSubRegisterSIMDType(GenTreeSIMD* simdNode)
- {
- unsigned vectorRegisterByteLength;
-#if defined(TARGET_XARCH)
- // Calling the getSIMDVectorRegisterByteLength api causes the size of Vector to be recorded
- // with the AOT compiler, so that it cannot change from aot compilation time to runtime
- // This api does not require such fixing as it merely pertains to the size of the simd type
- // relative to the Vector size as used at compile time. (So detecting a vector length of 16 here
- // does not preclude the code from being used on a machine with a larger vector length.)
- if (getSIMDSupportLevel() < SIMD_AVX2_Supported)
- {
- vectorRegisterByteLength = 16;
- }
- else
- {
- vectorRegisterByteLength = 32;
- }
-#else
- vectorRegisterByteLength = getSIMDVectorRegisterByteLength();
-#endif
- return (simdNode->GetSimdSize() < vectorRegisterByteLength);
- }
-
// Get the type for the hardware SIMD vector.
// This is the maximum SIMD type supported for this target.
var_types getSIMDVectorType()
@@ -10973,13 +10934,8 @@ class GenTreeVisitor
break;
}
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
if (TVisitor::UseExecutionOrder && node->IsReverseOp())
{
assert(node->AsMultiOp()->GetOperandCount() == 2);
@@ -11007,7 +10963,7 @@ class GenTreeVisitor
}
}
break;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // defined(FEATURE_HW_INTRINSICS)
case GT_SELECT:
{
diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp
index 946866d63c888..ea4a027400ecb 100644
--- a/src/coreclr/jit/compiler.hpp
+++ b/src/coreclr/jit/compiler.hpp
@@ -4125,13 +4125,8 @@ void GenTree::VisitOperands(TVisitor visitor)
return;
// Variadic nodes
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
for (GenTree* operand : this->AsMultiOp()->Operands())
{
if (visitor(operand) == VisitResult::Abort)
@@ -4140,7 +4135,7 @@ void GenTree::VisitOperands(TVisitor visitor)
}
}
return;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // defined(FEATURE_HW_INTRINSICS)
// Special nodes
case GT_PHI:
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 2ffcd3ae2e0d4..a3a59a17927dd 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -351,10 +351,6 @@ void GenTree::InitNodeSize()
#endif // FEATURE_ARG_SPLIT
#endif // FEATURE_PUT_STRUCT_ARG_STK
-#ifdef FEATURE_SIMD
- static_assert_no_msg(sizeof(GenTreeSIMD) <= TREE_NODE_SZ_SMALL);
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
static_assert_no_msg(sizeof(GenTreeHWIntrinsic) <= TREE_NODE_SZ_SMALL);
#endif // FEATURE_HW_INTRINSICS
@@ -2659,11 +2655,6 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK)
case GT_CALL:
return GenTreeCall::Equals(op1->AsCall(), op2->AsCall());
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- return GenTreeSIMD::Equals(op1->AsSIMD(), op2->AsSIMD());
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
return GenTreeHWIntrinsic::Equals(op1->AsHWIntrinsic(), op2->AsHWIntrinsic());
@@ -3078,14 +3069,6 @@ unsigned Compiler::gtHashValue(GenTree* tree)
case GT_INDEX_ADDR:
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- hash += tree->AsSIMD()->GetSIMDIntrinsicId();
- hash += tree->AsSIMD()->GetSimdBaseType();
- hash += tree->AsSIMD()->GetSimdSize();
- break;
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
hash += tree->AsHWIntrinsic()->GetHWIntrinsicId();
@@ -3181,20 +3164,15 @@ unsigned Compiler::gtHashValue(GenTree* tree)
break;
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
// TODO-List: rewrite with a general visitor / iterator?
for (GenTree* operand : tree->AsMultiOp()->Operands())
{
hash = genTreeHashAdd(hash, gtHashValue(operand));
}
break;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // FEATURE_HW_INTRINSICS
case GT_PHI:
for (GenTreePhi::Use& use : tree->AsPhi()->Uses())
@@ -5001,6 +4979,20 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
costEx = 36;
costSz = 4;
break;
+
+#if defined(FEATURE_SIMD)
+ case NI_SIMD_UpperRestore:
+ case NI_SIMD_UpperSave:
+ {
+ // TODO-CQ: 1 Ex/Sz isn't necessarily "accurate" but it is what the previous
+ // cost was computed as, in gtSetMultiOpOrder, when this was handled by the
+ // older SIMD intrinsic support.
+
+ costEx = 1;
+ costSz = 1;
+ break;
+ }
+#endif // FEATURE_SIMD
}
level++;
break;
@@ -5715,15 +5707,10 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
costEx += 3 * IND_COST_EX;
break;
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
return gtSetMultiOpOrder(tree->AsMultiOp());
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // FEATURE_HW_INTRINSICS
case GT_ARR_ELEM:
{
@@ -6084,13 +6071,8 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse)
return false;
#endif // FEATURE_ARG_SPLIT
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
for (GenTree** opUse : this->AsMultiOp()->UseEdges())
{
if (*opUse == operand)
@@ -6100,7 +6082,7 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse)
}
}
return false;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // FEATURE_HW_INTRINSICS
// Special nodes
case GT_PHI:
@@ -8045,7 +8027,7 @@ GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, bool isVo
// should be labeled as simd intrinsic related struct. This is done so that
// we do not promote the local, thus avoiding conflicting access methods
// (fields vs. whole-register).
- if (varTypeIsSIMD(srcOrFillVal) && srcOrFillVal->OperIsSimdOrHWintrinsic())
+ if (varTypeIsSIMD(srcOrFillVal) && srcOrFillVal->OperIsHWIntrinsic())
{
// TODO-Cleanup: similar logic already exists in "gtNewAssignNode",
// however, it is not enabled for x86. Fix that and delete this code.
@@ -8770,14 +8752,6 @@ GenTree* Compiler::gtCloneExpr(
copy = gtCloneExprCallHelper(tree->AsCall(), addFlags, deepVarNum, deepVarVal);
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- copy = new (this, GT_SIMD)
- GenTreeSIMD(tree->TypeGet(), IntrinsicNodeBuilder(getAllocator(CMK_ASTNode), tree->AsSIMD()),
- tree->AsSIMD()->GetSIMDIntrinsicId(), tree->AsSIMD()->GetSimdBaseJitType(),
- tree->AsSIMD()->GetSimdSize());
- goto CLONE_MULTIOP_OPERANDS;
-#endif
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
copy = new (this, GT_HWINTRINSIC)
@@ -9462,16 +9436,11 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
return;
// Variadic nodes
-#ifdef FEATURE_SIMD
- case GT_SIMD:
-#endif
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
-#endif
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
SetEntryStateForMultiOp();
return;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // FEATURE_HW_INTRINSICS
// LEA, which may have no first operand
case GT_LEA:
@@ -9746,7 +9715,7 @@ void GenTreeUseEdgeIterator::SetEntryStateForBinOp()
void GenTreeUseEdgeIterator::AdvanceMultiOp()
{
assert(m_node != nullptr);
- assert(m_node->OperIs(GT_SIMD, GT_HWINTRINSIC));
+ assert(m_node->OperIs(GT_HWINTRINSIC));
m_edge++;
if (m_edge == m_statePtr)
@@ -9765,7 +9734,7 @@ void GenTreeUseEdgeIterator::AdvanceMultiOp()
void GenTreeUseEdgeIterator::AdvanceReversedMultiOp()
{
assert(m_node != nullptr);
- assert(m_node->OperIs(GT_SIMD, GT_HWINTRINSIC));
+ assert(m_node->OperIs(GT_HWINTRINSIC));
assert((m_node->AsMultiOp()->GetOperandCount() == 2) && m_node->IsReverseOp());
m_edge--;
@@ -11681,14 +11650,6 @@ void Compiler::gtDispChild(GenTree* child,
indentStack->Pop();
}
-#ifdef FEATURE_SIMD
-// Intrinsic Id to name map
-extern const char* const simdIntrinsicNames[] = {
-#define SIMD_INTRINSIC(mname, inst, id, name, r, ac, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) name,
-#include "simdintrinsiclist.h"
-};
-#endif // FEATURE_SIMD
-
/*****************************************************************************/
void Compiler::gtDispTree(GenTree* tree,
@@ -12138,22 +12099,8 @@ void Compiler::gtDispTree(GenTree* tree,
}
break;
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
-
-#if defined(FEATURE_SIMD)
- if (tree->OperIs(GT_SIMD))
- {
- printf(" %s %s", varTypeName(tree->AsSIMD()->GetSimdBaseType()),
- simdIntrinsicNames[tree->AsSIMD()->GetSIMDIntrinsicId()]);
- }
-#endif // defined(FEATURE_SIMD)
-#if defined(FEATURE_HW_INTRINSICS)
if (tree->OperIs(GT_HWINTRINSIC))
{
printf(" %s %s", tree->AsHWIntrinsic()->GetSimdBaseType() == TYP_UNKNOWN
@@ -12161,7 +12108,6 @@ void Compiler::gtDispTree(GenTree* tree,
: varTypeName(tree->AsHWIntrinsic()->GetSimdBaseType()),
HWIntrinsicInfo::lookupName(tree->AsHWIntrinsic()->GetHWIntrinsicId()));
}
-#endif // defined(FEATURE_HW_INTRINSICS)
gtDispCommonEndLine(tree);
@@ -12175,7 +12121,7 @@ void Compiler::gtDispTree(GenTree* tree,
}
}
break;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // defined(FEATURE_HW_INTRINSICS)
case GT_ARR_ELEM:
gtDispCommonEndLine(tree);
@@ -14399,12 +14345,6 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree)
return tree;
}
-#ifdef FEATURE_SIMD
- if (tree->OperIs(GT_SIMD))
- {
- return tree;
- }
-#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
if (tree->OperIs(GT_HWINTRINSIC))
{
@@ -17613,9 +17553,6 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree)
structHnd = gtGetCanonicalStructHandleForSIMD(tree->TypeGet());
}
break;
- case GT_SIMD:
- structHnd = gtGetStructHandleForSIMD(tree->gtType, tree->AsSIMD()->GetSimdBaseJitType());
- break;
case GT_CNS_VEC:
structHnd = gtGetCanonicalStructHandleForSIMD(tree->TypeGet());
break;
@@ -18599,33 +18536,6 @@ FieldSeq::FieldSeq(CORINFO_FIELD_HANDLE fieldHnd, ssize_t offset, FieldKind fiel
}
#ifdef FEATURE_SIMD
-GenTreeSIMD* Compiler::gtNewSIMDNode(
- var_types type, GenTree* op1, SIMDIntrinsicID simdIntrinsicID, CorInfoType simdBaseJitType, unsigned simdSize)
-{
- assert(op1 != nullptr);
- SetOpLclRelatedToSIMDIntrinsic(op1);
-
- GenTreeSIMD* simdNode = new (this, GT_SIMD)
- GenTreeSIMD(type, getAllocator(CMK_ASTNode), op1, simdIntrinsicID, simdBaseJitType, simdSize);
- return simdNode;
-}
-
-GenTreeSIMD* Compiler::gtNewSIMDNode(var_types type,
- GenTree* op1,
- GenTree* op2,
- SIMDIntrinsicID simdIntrinsicID,
- CorInfoType simdBaseJitType,
- unsigned simdSize)
-{
- assert(op1 != nullptr);
- SetOpLclRelatedToSIMDIntrinsic(op1);
- SetOpLclRelatedToSIMDIntrinsic(op2);
-
- GenTreeSIMD* simdNode = new (this, GT_SIMD)
- GenTreeSIMD(type, getAllocator(CMK_ASTNode), op1, op2, simdIntrinsicID, simdBaseJitType, simdSize);
- return simdNode;
-}
-
//-------------------------------------------------------------------
// SetOpLclRelatedToSIMDIntrinsic: Determine if the tree has a local var that needs to be set
// as used by a SIMD intrinsic, and if so, set that local var appropriately.
@@ -18746,13 +18656,6 @@ var_types GenTreeJitIntrinsic::GetSimdBaseType() const
}
return JitType2PreciseVarType(simdBaseJitType);
}
-
-/* static */ bool GenTreeSIMD::Equals(GenTreeSIMD* op1, GenTreeSIMD* op2)
-{
- return (op1->TypeGet() == op2->TypeGet()) && (op1->GetSIMDIntrinsicId() == op2->GetSIMDIntrinsicId()) &&
- (op1->GetSimdBaseType() == op2->GetSimdBaseType()) && (op1->GetSimdSize() == op2->GetSimdSize()) &&
- OperandsAreEqual(op1, op2);
-}
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h
index a7cd6c5600ecb..780953c5c0cf7 100644
--- a/src/coreclr/jit/gentree.h
+++ b/src/coreclr/jit/gentree.h
@@ -1088,7 +1088,7 @@ struct GenTree
if (gtType == TYP_VOID)
{
// These are the only operators which can produce either VOID or non-VOID results.
- assert(OperIs(GT_NOP, GT_CALL, GT_COMMA) || OperIsCompare() || OperIsLong() || OperIsSimdOrHWintrinsic() ||
+ assert(OperIs(GT_NOP, GT_CALL, GT_COMMA) || OperIsCompare() || OperIsLong() || OperIsHWIntrinsic() ||
IsCnsVec());
return false;
}
@@ -1642,7 +1642,7 @@ struct GenTree
static bool OperIsMultiOp(genTreeOps gtOper)
{
- return OperIsSIMD(gtOper) || OperIsHWIntrinsic(gtOper);
+ return OperIsHWIntrinsic(gtOper);
}
bool OperIsMultiOp() const
@@ -1655,21 +1655,6 @@ struct GenTree
return OperIs(GT_ASG, GT_CALL);
}
- // This is here for cleaner FEATURE_SIMD #ifdefs.
- static bool OperIsSIMD(genTreeOps gtOper)
- {
-#ifdef FEATURE_SIMD
- return gtOper == GT_SIMD;
-#else // !FEATURE_SIMD
- return false;
-#endif // !FEATURE_SIMD
- }
-
- bool OperIsSIMD() const
- {
- return OperIsSIMD(gtOper);
- }
-
static bool OperIsHWIntrinsic(genTreeOps gtOper)
{
#ifdef FEATURE_HW_INTRINSICS
@@ -1684,11 +1669,6 @@ struct GenTree
return OperIsHWIntrinsic(gtOper);
}
- bool OperIsSimdOrHWintrinsic() const
- {
- return OperIsSIMD() || OperIsHWIntrinsic();
- }
-
// This is here for cleaner GT_LONG #ifdefs.
static bool OperIsLong(genTreeOps gtOper)
{
@@ -5587,7 +5567,7 @@ struct GenTreeCall final : public GenTree
bool mayUseDispatcher = true;
// Branch predictors on ARM64 generally do not handle the dispatcher as
// well as on x64 hardware, so only use the validator by default.
- bool shouldUseDispatcher = false;
+ bool shouldUseDispatcher = false;
#else
// Other platforms do not even support the dispatcher.
bool mayUseDispatcher = false;
@@ -6130,20 +6110,12 @@ struct GenTreeJitIntrinsic : public GenTreeMultiOp
{
protected:
GenTree* gtInlineOperands[2];
- regNumberSmall gtOtherReg; // The second register for multi-reg intrinsics.
- MultiRegSpillFlags gtSpillFlags; // Spill flags for multi-reg intrinsics.
- unsigned char gtAuxiliaryJitType; // For intrinsics than need another type (e.g. Avx2.Gather* or SIMD (by element))
- unsigned char gtSimdBaseJitType; // SIMD vector base JIT type
- unsigned char gtSimdSize; // SIMD vector size in bytes, use 0 for scalar intrinsics
-
-#if defined(FEATURE_SIMD)
- union {
- SIMDIntrinsicID gtSIMDIntrinsicID; // operation Id
- NamedIntrinsic gtHWIntrinsicId;
- };
-#else
+ regNumberSmall gtOtherReg; // The second register for multi-reg intrinsics.
+ MultiRegSpillFlags gtSpillFlags; // Spill flags for multi-reg intrinsics.
+ unsigned char gtAuxiliaryJitType; // For intrinsics than need another type (e.g. Avx2.Gather* or SIMD (by element))
+ unsigned char gtSimdBaseJitType; // SIMD vector base JIT type
+ unsigned char gtSimdSize; // SIMD vector size in bytes, use 0 for scalar intrinsics
NamedIntrinsic gtHWIntrinsicId;
-#endif
public:
regNumber GetOtherReg() const
@@ -6286,59 +6258,6 @@ struct GenTreeJitIntrinsic : public GenTreeMultiOp
}
};
-#ifdef FEATURE_SIMD
-
-/* gtSIMD -- SIMD intrinsic (possibly-binary op [NULL op2 is allowed] with additional fields) */
-struct GenTreeSIMD : public GenTreeJitIntrinsic
-{
- GenTreeSIMD(var_types type,
- IntrinsicNodeBuilder&& nodeBuilder,
- SIMDIntrinsicID simdIntrinsicID,
- CorInfoType simdBaseJitType,
- unsigned simdSize)
- : GenTreeJitIntrinsic(GT_SIMD, type, std::move(nodeBuilder), simdBaseJitType, simdSize)
- {
- gtSIMDIntrinsicID = simdIntrinsicID;
- }
-
- GenTreeSIMD(var_types type,
- CompAllocator allocator,
- GenTree* op1,
- SIMDIntrinsicID simdIntrinsicID,
- CorInfoType simdBaseJitType,
- unsigned simdSize)
- : GenTreeJitIntrinsic(GT_SIMD, type, allocator, simdBaseJitType, simdSize, op1)
- {
- gtSIMDIntrinsicID = simdIntrinsicID;
- }
-
- GenTreeSIMD(var_types type,
- CompAllocator allocator,
- GenTree* op1,
- GenTree* op2,
- SIMDIntrinsicID simdIntrinsicID,
- CorInfoType simdBaseJitType,
- unsigned simdSize)
- : GenTreeJitIntrinsic(GT_SIMD, type, allocator, simdBaseJitType, simdSize, op1, op2)
- {
- gtSIMDIntrinsicID = simdIntrinsicID;
- }
-
-#if DEBUGGABLE_GENTREE
- GenTreeSIMD() : GenTreeJitIntrinsic()
- {
- }
-#endif
-
- SIMDIntrinsicID GetSIMDIntrinsicId() const
- {
- return gtSIMDIntrinsicID;
- }
-
- static bool Equals(GenTreeSIMD* op1, GenTreeSIMD* op2);
-};
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
struct GenTreeHWIntrinsic : public GenTreeJitIntrinsic
{
diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h
index cf6f508fd1277..a0650f1d0dc05 100644
--- a/src/coreclr/jit/gtlist.h
+++ b/src/coreclr/jit/gtlist.h
@@ -189,10 +189,6 @@ GTNODE(RSH_LO , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
GTNODE(SELECT_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
#endif // !defined(TARGET_64BIT)
-#ifdef FEATURE_SIMD
-GTNODE(SIMD , GenTreeSIMD ,0,GTK_SPECIAL) // SIMD functions/operators/intrinsics
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,GTK_SPECIAL) // hardware intrinsics
#endif // FEATURE_HW_INTRINSICS
diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h
index ae62bde014a5a..0321f51a95c00 100644
--- a/src/coreclr/jit/gtstructs.h
+++ b/src/coreclr/jit/gtstructs.h
@@ -73,11 +73,7 @@ GTSTRUCT_1(Colon , GT_COLON)
GTSTRUCT_1(FptrVal , GT_FTN_ADDR)
GTSTRUCT_1(Intrinsic , GT_INTRINSIC)
GTSTRUCT_1(IndexAddr , GT_INDEX_ADDR)
-#if defined(FEATURE_HW_INTRINSICS) && defined(FEATURE_SIMD)
-GTSTRUCT_N(MultiOp , GT_SIMD, GT_HWINTRINSIC)
-#elif defined(FEATURE_SIMD)
-GTSTRUCT_N(MultiOp , GT_SIMD)
-#elif defined(FEATURE_HW_INTRINSICS)
+#if defined(FEATURE_HW_INTRINSICS)
GTSTRUCT_N(MultiOp , GT_HWINTRINSIC)
#endif
GTSTRUCT_1(BoundsChk , GT_BOUNDS_CHECK)
@@ -109,9 +105,6 @@ GTSTRUCT_1(PutArgSplit , GT_PUTARG_SPLIT)
GTSTRUCT_1(PutArgStk , GT_PUTARG_STK)
#endif // !FEATURE_ARG_SPLIT
GTSTRUCT_1(PhysReg , GT_PHYSREG)
-#ifdef FEATURE_SIMD
-GTSTRUCT_1(SIMD , GT_SIMD)
-#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
GTSTRUCT_1(HWIntrinsic , GT_HWINTRINSIC)
#endif // FEATURE_HW_INTRINSICS
diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp
index eda9ce179b639..d1af2c46f630b 100644
--- a/src/coreclr/jit/importer.cpp
+++ b/src/coreclr/jit/importer.cpp
@@ -1196,7 +1196,7 @@ GenTree* Compiler::impGetStructAddr(GenTree* structVal,
genTreeOps oper = structVal->gtOper;
if (oper == GT_CALL || oper == GT_RET_EXPR || (oper == GT_OBJ && !willDeref) || oper == GT_MKREFANY ||
- structVal->OperIsSimdOrHWintrinsic() || structVal->IsCnsVec())
+ structVal->OperIsHWIntrinsic() || structVal->IsCnsVec())
{
unsigned tmpNum = lvaGrabTemp(true DEBUGARG("struct address for call/obj"));
@@ -1342,9 +1342,6 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str
case GT_BLK:
case GT_FIELD:
case GT_CNS_VEC:
-#ifdef FEATURE_SIMD
- case GT_SIMD:
-#endif
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
#endif
@@ -1355,7 +1352,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str
case GT_COMMA:
{
- // The second thing could either be a block node or a GT_FIELD or a GT_SIMD or a GT_COMMA node.
+ // The second thing could either be a block node or a GT_FIELD or a GT_COMMA node.
GenTree* blockNode = structVal->AsOp()->gtOp2;
assert(blockNode->gtType == structType);
@@ -1373,7 +1370,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str
}
#ifdef FEATURE_SIMD
- if (blockNode->OperIsSimdOrHWintrinsic() || blockNode->IsCnsVec())
+ if (blockNode->OperIsHWIntrinsic() || blockNode->IsCnsVec())
{
parent->AsOp()->gtOp2 = impNormStructVal(blockNode, structHnd, curLevel);
}
diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp
index 9a2180983bc0a..b9cd308c66781 100644
--- a/src/coreclr/jit/lower.cpp
+++ b/src/coreclr/jit/lower.cpp
@@ -1344,7 +1344,7 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late)
const LclVarDsc* varDsc = comp->lvaGetDesc(arg->AsLclVarCommon());
type = varDsc->lvType;
}
- else if (arg->OperIs(GT_SIMD, GT_HWINTRINSIC))
+ else if (arg->OperIs(GT_HWINTRINSIC))
{
GenTreeJitIntrinsic* jitIntrinsic = reinterpret_cast(arg);
@@ -6639,7 +6639,6 @@ void Lowering::CheckNode(Compiler* compiler, GenTree* node)
break;
#ifdef FEATURE_SIMD
- case GT_SIMD:
case GT_HWINTRINSIC:
assert(node->TypeGet() != TYP_SIMD12);
break;
diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp
index 1203485793fa6..0e1cf0770a9df 100644
--- a/src/coreclr/jit/lsra.cpp
+++ b/src/coreclr/jit/lsra.cpp
@@ -6311,24 +6311,15 @@ void LinearScan::insertUpperVectorSave(GenTree* tree,
saveLcl->SetRegNum(lclVarReg);
SetLsraAdded(saveLcl);
- GenTreeSIMD* simdNode = compiler->gtNewSIMDNode(LargeVectorSaveType, saveLcl, SIMDIntrinsicUpperSave,
- varDsc->GetSimdBaseJitType(), genTypeSize(varDsc));
+ GenTreeIntrinsic* simdUpperSave =
+ new (compiler, GT_INTRINSIC) GenTreeIntrinsic(LargeVectorSaveType, saveLcl, NI_SIMD_UpperSave, nullptr);
- if (simdNode->GetSimdBaseJitType() == CORINFO_TYPE_UNDEF)
- {
- // There are a few scenarios where we can get a LCL_VAR which
- // doesn't know the underlying baseType. In that scenario, we
- // will just lie and say it is a float. Codegen doesn't actually
- // care what the type is but this avoids an assert that would
- // otherwise be fired from the more general checks that happen.
- simdNode->SetSimdBaseJitType(CORINFO_TYPE_FLOAT);
- }
+ SetLsraAdded(simdUpperSave);
+ simdUpperSave->SetRegNum(spillReg);
- SetLsraAdded(simdNode);
- simdNode->SetRegNum(spillReg);
if (spillToMem)
{
- simdNode->gtFlags |= GTF_SPILL;
+ simdUpperSave->gtFlags |= GTF_SPILL;
upperVectorInterval->physReg = REG_NA;
}
else
@@ -6337,8 +6328,8 @@ void LinearScan::insertUpperVectorSave(GenTree* tree,
upperVectorInterval->physReg = spillReg;
}
- blockRange.InsertBefore(tree, LIR::SeqTree(compiler, simdNode));
- DISPTREE(simdNode);
+ blockRange.InsertBefore(tree, LIR::SeqTree(compiler, simdUpperSave));
+ DISPTREE(simdUpperSave);
JITDUMP("\n");
}
@@ -6377,21 +6368,11 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree,
restoreLcl->SetRegNum(lclVarReg);
SetLsraAdded(restoreLcl);
- GenTreeSIMD* simdNode = compiler->gtNewSIMDNode(varDsc->TypeGet(), restoreLcl, SIMDIntrinsicUpperRestore,
- varDsc->GetSimdBaseJitType(), genTypeSize(varDsc->lvType));
-
- if (simdNode->GetSimdBaseJitType() == CORINFO_TYPE_UNDEF)
- {
- // There are a few scenarios where we can get a LCL_VAR which
- // doesn't know the underlying baseType. In that scenario, we
- // will just lie and say it is a float. Codegen doesn't actually
- // care what the type is but this avoids an assert that would
- // otherwise be fired from the more general checks that happen.
- simdNode->SetSimdBaseJitType(CORINFO_TYPE_FLOAT);
- }
+ GenTreeIntrinsic* simdUpperRestore =
+ new (compiler, GT_INTRINSIC) GenTreeIntrinsic(varDsc->TypeGet(), restoreLcl, NI_SIMD_UpperRestore, nullptr);
regNumber restoreReg = upperVectorInterval->physReg;
- SetLsraAdded(simdNode);
+ SetLsraAdded(simdUpperRestore);
if (restoreReg == REG_NA)
{
@@ -6399,14 +6380,14 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree,
assert(lclVarInterval->isSpilled);
#ifdef TARGET_AMD64
assert(refPosition->assignedReg() == REG_NA);
- simdNode->gtFlags |= GTF_NOREG_AT_USE;
+ simdUpperRestore->gtFlags |= GTF_NOREG_AT_USE;
#else
- simdNode->gtFlags |= GTF_SPILLED;
+ simdUpperRestore->gtFlags |= GTF_SPILLED;
assert(refPosition->assignedReg() != REG_NA);
restoreReg = refPosition->assignedReg();
#endif
}
- simdNode->SetRegNum(restoreReg);
+ simdUpperRestore->SetRegNum(restoreReg);
LIR::Range& blockRange = LIR::AsRange(block);
if (tree != nullptr)
@@ -6416,7 +6397,7 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree,
bool foundUse = blockRange.TryGetUse(tree, &treeUse);
assert(foundUse);
// We need to insert the restore prior to the use, not (necessarily) immediately after the lclVar.
- blockRange.InsertBefore(treeUse.User(), LIR::SeqTree(compiler, simdNode));
+ blockRange.InsertBefore(treeUse.User(), LIR::SeqTree(compiler, simdUpperRestore));
}
else
{
@@ -6429,15 +6410,15 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree,
assert(branch->OperIsConditionalJump() || branch->OperGet() == GT_SWITCH_TABLE ||
branch->OperGet() == GT_SWITCH);
- blockRange.InsertBefore(branch, LIR::SeqTree(compiler, simdNode));
+ blockRange.InsertBefore(branch, LIR::SeqTree(compiler, simdUpperRestore));
}
else
{
assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS));
- blockRange.InsertAtEnd(LIR::SeqTree(compiler, simdNode));
+ blockRange.InsertAtEnd(LIR::SeqTree(compiler, simdUpperRestore));
}
}
- DISPTREE(simdNode);
+ DISPTREE(simdUpperRestore);
JITDUMP("\n");
}
#endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index 14403a8c0f796..d2fd606accd11 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -12749,16 +12749,11 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac)
tree = fgMorphCall(tree->AsCall());
break;
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
#if defined(FEATURE_HW_INTRINSICS)
case GT_HWINTRINSIC:
-#endif
tree = fgMorphMultiOp(tree->AsMultiOp());
break;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
+#endif // FEATURE_HW_INTRINSICS
case GT_ARR_ELEM:
tree->AsArrElem()->gtArrObj = fgMorphTree(tree->AsArrElem()->gtArrObj);
diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h
index 37af303c0ab68..dd58663b6505c 100644
--- a/src/coreclr/jit/namedintrinsiclist.h
+++ b/src/coreclr/jit/namedintrinsiclist.h
@@ -148,6 +148,11 @@ enum NamedIntrinsic : unsigned short
NI_SIMD_AS_HWINTRINSIC_END,
#endif // FEATURE_HW_INTRINSICS
+#if defined(FEATURE_SIMD)
+ NI_SIMD_UpperRestore,
+ NI_SIMD_UpperSave,
+#endif // FEATURE_SIMD
+
NI_SRCS_UNSAFE_START,
NI_SRCS_UNSAFE_Add,
diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp
index efd8ffb0f26b4..fa21ea5b8facd 100644
--- a/src/coreclr/jit/optcse.cpp
+++ b/src/coreclr/jit/optcse.cpp
@@ -3666,12 +3666,6 @@ bool Compiler::optIsCSEcandidate(GenTree* tree)
case GT_GT:
return true; // Allow the CSE of Comparison operators
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- return true; // allow SIMD intrinsics to be CSE-ed
-
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
{
diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp
index 8f18908134f51..d73d4d779e9e9 100644
--- a/src/coreclr/jit/simd.cpp
+++ b/src/coreclr/jit/simd.cpp
@@ -8,7 +8,7 @@
//
// This implementation is preliminary, and may change dramatically.
//
-// New JIT types, TYP_SIMDxx, are introduced, and the SIMD intrinsics are created as GT_SIMD nodes.
+// New JIT types, TYP_SIMDxx, are introduced, and the hwintrinsics are created as GT_HWINTRINSC nodes.
// Nodes of SIMD types will be typed as TYP_SIMD* (e.g. TYP_SIMD8, TYP_SIMD16, etc.).
//
// Note that currently the "reference implementation" is the same as the runtime dll. As such, it is currently
@@ -30,15 +30,6 @@
#endif
#ifdef FEATURE_SIMD
-
-// Intrinsic Id to intrinsic info map
-const SIMDIntrinsicInfo simdIntrinsicInfoArray[] = {
-#define SIMD_INTRINSIC(mname, inst, id, name, retType, argCount, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, \
- t10) \
- {SIMDIntrinsic##id, mname, inst, retType, argCount, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10},
-#include "simdintrinsiclist.h"
-};
-
//------------------------------------------------------------------------
// getSIMDVectorLength: Get the length (number of elements of base type) of
// SIMD Vector given its size and base (element) type.
diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h
index f59c09b72a7c0..be227acf2bcaf 100644
--- a/src/coreclr/jit/simd.h
+++ b/src/coreclr/jit/simd.h
@@ -144,28 +144,6 @@ struct simd32_t
#ifdef FEATURE_SIMD
-#ifdef DEBUG
-extern const char* const simdIntrinsicNames[];
-#endif
-
-enum SIMDIntrinsicID : uint16_t
-{
-#define SIMD_INTRINSIC(m, i, id, n, r, ac, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) SIMDIntrinsic##id,
-#include "simdintrinsiclist.h"
-};
-
-// Static info about a SIMD intrinsic
-struct SIMDIntrinsicInfo
-{
- SIMDIntrinsicID id;
- const char* methodName;
- bool isInstMethod;
- var_types retType;
- unsigned char argCount;
- var_types argType[SIMD_INTRINSIC_MAX_MODELED_PARAM_COUNT];
- var_types supportedBaseTypes[SIMD_INTRINSIC_MAX_BASETYPE_COUNT];
-};
-
#ifdef TARGET_XARCH
// SSE2 Shuffle control byte to shuffle vector
// These correspond to shuffle immediate byte in shufps SSE2 instruction.
diff --git a/src/coreclr/jit/simdcodegenxarch.cpp b/src/coreclr/jit/simdcodegenxarch.cpp
index a05e281fa54ef..68e7236101625 100644
--- a/src/coreclr/jit/simdcodegenxarch.cpp
+++ b/src/coreclr/jit/simdcodegenxarch.cpp
@@ -285,11 +285,11 @@ void CodeGen::genPutArgStkSIMD12(GenTree* treeNode)
#endif // TARGET_X86
//-----------------------------------------------------------------------------
-// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD32 vector to
-// the given register, if any, or to memory.
+// genSimdUpperSave: save the upper half of a TYP_SIMD32 vector to
+// the given register, if any, or to memory.
//
// Arguments:
-// simdNode - The GT_SIMD node
+// node - The GT_INTRINSIC node
//
// Return Value:
// None.
@@ -303,26 +303,30 @@ void CodeGen::genPutArgStkSIMD12(GenTree* treeNode)
// (Note that if there are no caller-save registers available, the entire 32 byte
// value will be spilled to the stack.)
//
-void CodeGen::genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode)
+void CodeGen::genSimdUpperSave(GenTreeIntrinsic* node)
{
- assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicUpperSave);
+ assert(node->gtIntrinsicName == NI_SIMD_UpperSave);
- GenTree* op1 = simdNode->Op(1);
- assert(op1->IsLocal() && op1->TypeGet() == TYP_SIMD32);
- regNumber targetReg = simdNode->GetRegNum();
- regNumber op1Reg = genConsumeReg(op1);
+ GenTree* op1 = node->gtGetOp1();
+ assert(op1->IsLocal() && (op1->TypeGet() == TYP_SIMD32));
+
+ regNumber tgtReg = node->GetRegNum();
+ regNumber op1Reg = genConsumeReg(op1);
assert(op1Reg != REG_NA);
- if (targetReg != REG_NA)
+
+ if (tgtReg != REG_NA)
{
- GetEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, targetReg, op1Reg, 0x01);
- genProduceReg(simdNode);
+ GetEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tgtReg, op1Reg, 0x01);
+ genProduceReg(node);
}
else
{
// The localVar must have a stack home.
+
unsigned varNum = op1->AsLclVarCommon()->GetLclNum();
LclVarDsc* varDsc = compiler->lvaGetDesc(varNum);
assert(varDsc->lvOnFrame);
+
// We want to store this to the upper 16 bytes of this localVar's home.
int offs = 16;
@@ -331,29 +335,31 @@ void CodeGen::genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode)
}
//-----------------------------------------------------------------------------
-// genSIMDIntrinsicUpperRestore: Restore the upper half of a TYP_SIMD32 vector to
-// the given register, if any, or to memory.
+// genSimdUpperRestore: Restore the upper half of a TYP_SIMD32 vector to
+// the given register, if any, or to memory.
//
// Arguments:
-// simdNode - The GT_SIMD node
+// node - The GT_INTRINSIC node
//
// Return Value:
// None.
//
// Notes:
-// For consistency with genSIMDIntrinsicUpperSave, and to ensure that lclVar nodes always
+// For consistency with genSimdUpperSave, and to ensure that lclVar nodes always
// have their home register, this node has its targetReg on the lclVar child, and its source
-// on the simdNode.
+// on the node.
//
-void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
+void CodeGen::genSimdUpperRestore(GenTreeIntrinsic* node)
{
- assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicUpperRestore);
+ assert(node->gtIntrinsicName == NI_SIMD_UpperRestore);
- GenTree* op1 = simdNode->Op(1);
+ GenTree* op1 = node->gtGetOp1();
assert(op1->IsLocal() && op1->TypeGet() == TYP_SIMD32);
- regNumber srcReg = simdNode->GetRegNum();
+
+ regNumber srcReg = node->GetRegNum();
regNumber lclVarReg = genConsumeReg(op1);
assert(lclVarReg != REG_NA);
+
if (srcReg != REG_NA)
{
GetEmitter()->emitIns_R_R_R_I(INS_vinsertf128, EA_32BYTE, lclVarReg, lclVarReg, srcReg, 0x01);
@@ -370,42 +376,5 @@ void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
}
}
-//------------------------------------------------------------------------
-// genSIMDIntrinsic: Generate code for a SIMD Intrinsic. This is the main
-// routine which in turn calls appropriate genSIMDIntrinsicXXX() routine.
-//
-// Arguments:
-// simdNode - The GT_SIMD node
-//
-// Return Value:
-// None.
-//
-// Notes:
-// Currently, we only recognize SIMDVector and SIMDVector, and
-// a limited set of methods.
-//
-void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
-{
- // NYI for unsupported base types
- if (!varTypeIsArithmetic(simdNode->GetSimdBaseType()))
- {
- noway_assert(!"SIMD intrinsic with unsupported base type.");
- }
-
- switch (simdNode->GetSIMDIntrinsicId())
- {
- case SIMDIntrinsicUpperSave:
- genSIMDIntrinsicUpperSave(simdNode);
- break;
- case SIMDIntrinsicUpperRestore:
- genSIMDIntrinsicUpperRestore(simdNode);
- break;
-
- default:
- noway_assert(!"Unimplemented SIMD intrinsic.");
- unreached();
- }
-}
-
#endif // FEATURE_SIMD
#endif // TARGET_XARCH
diff --git a/src/coreclr/jit/simdintrinsiclist.h b/src/coreclr/jit/simdintrinsiclist.h
deleted file mode 100644
index 74beb2db3d8ca..0000000000000
--- a/src/coreclr/jit/simdintrinsiclist.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*****************************************************************************/
-#ifndef SIMD_INTRINSIC
-#error Define SIMD_INTRINSIC before including this file
-#endif
-/*****************************************************************************/
-
-// clang-format off
-#ifdef FEATURE_SIMD
-
- /*
- Notes:
- a) TYP_UNKNOWN means 'baseType' of SIMD vector which is not known apriori
- b) Each method maps to a unique intrinsic Id
- c) To facilitate argument types to be used as an array initializer, args are listed within "{}" braces.
- d) Since comma is used as actual param separator in a macro, TYP_UNDEF entries are added to keep param count constant.
- e) TODO-Cleanup: when we plumb TYP_SIMD through front-end, replace TYP_STRUCT with TYP_SIMD.
- */
-
-#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
-
-// Max number of parameters that we model in the table for SIMD intrinsic methods.
-#define SIMD_INTRINSIC_MAX_MODELED_PARAM_COUNT 3
-
-// Actual maximum number of parameters for any SIMD intrinsic method.
-// Constructors that take either N values, or a smaller Vector plus additional element values,
-// actually have more arguments than the "modeled" count.
-#define SIMD_INTRINSIC_MAX_PARAM_COUNT 5
-
-// Max number of base types supported by an intrinsic
-#define SIMD_INTRINSIC_MAX_BASETYPE_COUNT 10
-
-/***************************************************************************************************************************************************************************************************************************
- Method Name, Is Instance Intrinsic Id, Display Name, return type, Arg count, Individual argument types Supported base types
- Method (including implicit "this")
- ***************************************************************************************************************************************************************************************************************************/
-SIMD_INTRINSIC(nullptr, false, None, "None", TYP_UNDEF, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF})
-
-// Internal intrinsics for saving & restoring the upper half of a vector register
-SIMD_INTRINSIC("UpperSave", false, UpperSave, "UpperSave Internal", TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF})
-SIMD_INTRINSIC("UpperRestore", false, UpperRestore, "UpperRestore Internal", TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF})
-
-SIMD_INTRINSIC(nullptr, false, Invalid, "Invalid", TYP_UNDEF, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF})
-#undef SIMD_INTRINSIC
-#else // !defined(TARGET_XARCH) && !defined(TARGET_ARM64)
-#error SIMD intrinsics not defined for target arch
-#endif // !defined(TARGET_XARCH) && !defined(TARGET_ARM64)
-
-
-#endif //FEATURE_SIMD
-// clang-format on
diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp
index b6c74e5fcc679..1bc05151623d1 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -341,10 +341,6 @@ VNFunc GetVNFuncForNode(GenTree* node)
}
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- return VNFunc(VNF_SIMD_FIRST + node->AsSIMD()->GetSIMDIntrinsicId());
-#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
return VNFunc(VNF_HWI_FIRST + (node->AsHWIntrinsic()->GetHWIntrinsicId() - NI_HW_INTRINSIC_START - 1));
@@ -9327,12 +9323,6 @@ void Compiler::fgValueNumberTree(GenTree* tree)
fgValueNumberCall(tree->AsCall());
break;
-#ifdef FEATURE_SIMD
- case GT_SIMD:
- fgValueNumberSimd(tree->AsSIMD());
- break;
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
fgValueNumberHWIntrinsic(tree->AsHWIntrinsic());
@@ -9561,68 +9551,6 @@ void Compiler::fgValueNumberArrIndexAddr(GenTreeArrAddr* arrAddr)
arrAddr->gtVNPair = vnStore->VNPWithExc(arrAddrVNP, vnStore->VNPExceptionSet(arrAddr->Addr()->gtVNPair));
}
-#ifdef FEATURE_SIMD
-// Does value-numbering for a GT_SIMD node.
-void Compiler::fgValueNumberSimd(GenTreeSIMD* tree)
-{
- VNFunc simdFunc = GetVNFuncForNode(tree);
- ValueNumPair excSetPair;
- ValueNumPair normalPair;
-
- if ((tree->GetOperandCount() > 2) || ((JitConfig.JitDisableSimdVN() & 1) == 1))
- {
- // We have a SIMD node with 3 or more args. To retain the
- // previous behavior, we will generate a unique VN for this case.
- excSetPair = ValueNumStore::VNPForEmptyExcSet();
- for (GenTree* operand : tree->Operands())
- {
- excSetPair = vnStore->VNPUnionExcSet(operand->gtVNPair, excSetPair);
- }
- tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), excSetPair);
- return;
- }
-
- // There are some SIMD operations that have zero args, i.e. NI_Vector128_Zero
- if (tree->GetOperandCount() == 0)
- {
- excSetPair = ValueNumStore::VNPForEmptyExcSet();
- normalPair = vnStore->VNPairForFunc(tree->TypeGet(), simdFunc);
- }
- else // SIMD unary or binary operator.
- {
- ValueNumPair resvnp = ValueNumPair();
- ValueNumPair op1vnp;
- ValueNumPair op1Xvnp;
- vnStore->VNPUnpackExc(tree->Op(1)->gtVNPair, &op1vnp, &op1Xvnp);
-
- ValueNum addrVN = ValueNumStore::NoVN;
-
- if (tree->GetOperandCount() == 1)
- {
- // A unary SIMD node.
- excSetPair = op1Xvnp;
- {
- normalPair = vnStore->VNPairForFunc(tree->TypeGet(), simdFunc, op1vnp);
- assert(vnStore->VNFuncArity(simdFunc) == 1);
- }
- }
- else
- {
- ValueNumPair op2vnp;
- ValueNumPair op2Xvnp;
- vnStore->VNPUnpackExc(tree->Op(2)->gtVNPair, &op2vnp, &op2Xvnp);
-
- excSetPair = vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp);
- {
- normalPair = vnStore->VNPairForFunc(tree->TypeGet(), simdFunc, op1vnp, op2vnp);
- assert(vnStore->VNFuncArity(simdFunc) == 2);
- }
- }
- }
- tree->gtVNPair = vnStore->VNPWithExc(normalPair, excSetPair);
-}
-#endif // FEATURE_SIMD
-
#ifdef FEATURE_HW_INTRINSICS
void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree)
{
diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h
index baaf1fc62a8f2..8dcb66c5f5669 100644
--- a/src/coreclr/jit/valuenumfuncs.h
+++ b/src/coreclr/jit/valuenumfuncs.h
@@ -168,11 +168,6 @@ ValueNumFuncDef(MUL_UN_OVF, 2, true, false, false)
ValueNumFuncDef(SimdType, 2, false, false, false) // A value number function to compose a SIMD type
#endif
-#define SIMD_INTRINSIC(m, i, id, n, r, argCount, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) \
-ValueNumFuncDef(SIMD_##id, argCount, false, false, false) // All of the SIMD intrinsic
-#include "simdintrinsiclist.h"
-#define VNF_SIMD_FIRST VNF_SIMD_None
-
#if defined(TARGET_XARCH)
#define HARDWARE_INTRINSIC(isa, name, size, argCount, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
ValueNumFuncDef(HWI_##isa##_##name, argCount, false, false, false) // All of the HARDWARE_INTRINSICS for x86/x64