diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index b74d0a8c8f84..40890e6a5e38 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1980,7 +1980,7 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) } genProduceReg(lclNode); #else // !UNIX_AMD64_ABI - assert(!"Multireg store to SIMD reg not supported on X64 Windows"); + assert(!"Multireg store to SIMD reg not supported on Windows"); #endif // !UNIX_AMD64_ABI } #endif // FEATURE_SIMD diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index eb809383761e..a466ede27203 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -6759,6 +6759,20 @@ GenTreeOp* Compiler::gtNewAssignNode(GenTree* dst, GenTree* src) } dst->gtFlags |= GTF_DONT_CSE; +#if defined(FEATURE_SIMD) && !defined(TARGET_X86) + // TODO-CQ: x86 Windows supports multi-reg returns but not SIMD multi-reg returns + + if (varTypeIsSIMD(dst->gtType)) + { + // We want to track SIMD assignments as being intrinsics since they + // are functionally SIMD `mov` instructions and are more efficient + // when we don't promote, particularly when it occurs due to inlining + + SetOpLclRelatedToSIMDIntrinsic(dst); + SetOpLclRelatedToSIMDIntrinsic(src); + } +#endif // FEATURE_SIMD + /* Create the assignment node */ GenTreeOp* asg = gtNewOperNode(GT_ASG, dst->TypeGet(), dst, src)->AsOp(); @@ -18937,16 +18951,27 @@ GenTreeSIMD* Compiler::gtNewSIMDNode(var_types type, // void Compiler::SetOpLclRelatedToSIMDIntrinsic(GenTree* op) { - if (op != nullptr) + if (op == nullptr) { - if (op->OperIsLocal()) - { - setLclRelatedToSIMDIntrinsic(op); - } - else if ((op->OperGet() == GT_OBJ) && (op->AsOp()->gtOp1->OperGet() == GT_ADDR) && - op->AsOp()->gtOp1->AsOp()->gtOp1->OperIsLocal()) + return; + } + + if (op->OperIsLocal()) + { + setLclRelatedToSIMDIntrinsic(op); + } + else if (op->OperIs(GT_OBJ)) + { + GenTree* addr = op->AsIndir()->Addr(); + + if (addr->OperIs(GT_ADDR)) { - setLclRelatedToSIMDIntrinsic(op->AsOp()->gtOp1->AsOp()->gtOp1); + GenTree* addrOp1 = addr->AsOp()->gtGetOp1(); + + if (addrOp1->OperIsLocal()) + { + setLclRelatedToSIMDIntrinsic(addrOp1); + } } } } diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 3901c057cc78..17e1ac42d606 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -4847,7 +4847,7 @@ struct GenTreeIntrinsic : public GenTreeOp struct GenTreeJitIntrinsic : public GenTreeOp { private: - ClassLayout* m_layout; + ClassLayout* gtLayout; unsigned char gtAuxiliaryJitType; // For intrinsics than need another type (e.g. Avx2.Gather* or SIMD (by element)) regNumberSmall gtOtherReg; // For intrinsics that return 2 registers @@ -4867,13 +4867,13 @@ struct GenTreeJitIntrinsic : public GenTreeOp ClassLayout* GetLayout() const { - return m_layout; + return gtLayout; } void SetLayout(ClassLayout* layout) { assert(layout != nullptr); - m_layout = layout; + gtLayout = layout; } regNumber GetOtherReg() const @@ -4927,6 +4927,9 @@ struct GenTreeJitIntrinsic : public GenTreeOp GenTreeJitIntrinsic( genTreeOps oper, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) : GenTreeOp(oper, type, op1, op2) + , gtLayout(nullptr) + , gtAuxiliaryJitType(CORINFO_TYPE_UNDEF) + , gtOtherReg(REG_NA) , gtSimdBaseJitType((unsigned char)simdBaseJitType) , gtSimdSize((unsigned char)simdSize) , gtHWIntrinsicId(NI_Illegal)