Skip to content

Commit 7814396

Browse files
echesakovimhameed
andauthored
Implement LoadPairVector64 and LoadPairVector128 (#64864)
Co-authored-by: Imran Hameed <[email protected]>
1 parent ccd67b0 commit 7814396

File tree

87 files changed

+14059
-676
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+14059
-676
lines changed

src/coreclr/jit/gentree.cpp

Lines changed: 126 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -706,14 +706,19 @@ int GenTree::GetRegisterDstCount(Compiler* compiler) const
706706
#endif
707707
}
708708
#endif
709-
710-
#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
711-
if (OperIs(GT_HWINTRINSIC))
709+
#ifdef FEATURE_HW_INTRINSICS
710+
else if (OperIsHWIntrinsic())
712711
{
713-
assert(TypeGet() == TYP_STRUCT);
714-
return 2;
712+
assert(TypeIs(TYP_STRUCT));
713+
714+
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
715+
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();
716+
assert(HWIntrinsicInfo::IsMultiReg(intrinsicId));
717+
718+
return HWIntrinsicInfo::GetMultiRegCount(intrinsicId);
715719
}
716-
#endif
720+
#endif // FEATURE_HW_INTRINSICS
721+
717722
if (OperIsScalarLocal())
718723
{
719724
return AsLclVar()->GetFieldCount(compiler);
@@ -722,6 +727,121 @@ int GenTree::GetRegisterDstCount(Compiler* compiler) const
722727
return 0;
723728
}
724729

730+
//-----------------------------------------------------------------------------------
731+
// IsMultiRegNode: whether a node returning its value in more than one register
732+
//
733+
// Arguments:
734+
// None
735+
//
736+
// Return Value:
737+
// Returns true if this GenTree is a multi-reg node.
738+
//
739+
// Notes:
740+
// All targets that support multi-reg ops of any kind also support multi-reg return
741+
// values for calls. Should that change with a future target, this method will need
742+
// to change accordingly.
743+
//
744+
bool GenTree::IsMultiRegNode() const
745+
{
746+
#if FEATURE_MULTIREG_RET
747+
if (IsMultiRegCall())
748+
{
749+
return true;
750+
}
751+
752+
#if FEATURE_ARG_SPLIT
753+
if (OperIsPutArgSplit())
754+
{
755+
return true;
756+
}
757+
#endif
758+
759+
#if !defined(TARGET_64BIT)
760+
if (OperIsMultiRegOp())
761+
{
762+
return true;
763+
}
764+
#endif
765+
766+
if (OperIs(GT_COPY, GT_RELOAD))
767+
{
768+
return true;
769+
}
770+
#endif // FEATURE_MULTIREG_RET
771+
772+
#ifdef FEATURE_HW_INTRINSICS
773+
if (OperIsHWIntrinsic())
774+
{
775+
return HWIntrinsicInfo::IsMultiReg(AsHWIntrinsic()->GetHWIntrinsicId());
776+
}
777+
#endif // FEATURE_HW_INTRINSICS
778+
779+
if (IsMultiRegLclVar())
780+
{
781+
return true;
782+
}
783+
return false;
784+
}
785+
786+
//-----------------------------------------------------------------------------------
787+
// GetMultiRegCount: Return the register count for a multi-reg node.
788+
//
789+
// Arguments:
790+
// None
791+
//
792+
// Return Value:
793+
// Returns the number of registers defined by this node.
794+
//
795+
unsigned GenTree::GetMultiRegCount() const
796+
{
797+
#if FEATURE_MULTIREG_RET
798+
if (IsMultiRegCall())
799+
{
800+
return AsCall()->GetReturnTypeDesc()->GetReturnRegCount();
801+
}
802+
803+
#if FEATURE_ARG_SPLIT
804+
if (OperIsPutArgSplit())
805+
{
806+
return AsPutArgSplit()->gtNumRegs;
807+
}
808+
#endif
809+
810+
#if !defined(TARGET_64BIT)
811+
if (OperIsMultiRegOp())
812+
{
813+
return AsMultiRegOp()->GetRegCount();
814+
}
815+
#endif
816+
817+
if (OperIs(GT_COPY, GT_RELOAD))
818+
{
819+
return AsCopyOrReload()->GetRegCount();
820+
}
821+
#endif // FEATURE_MULTIREG_RET
822+
823+
#ifdef FEATURE_HW_INTRINSICS
824+
if (OperIsHWIntrinsic())
825+
{
826+
return HWIntrinsicInfo::GetMultiRegCount(AsHWIntrinsic()->GetHWIntrinsicId());
827+
}
828+
#endif // FEATURE_HW_INTRINSICS
829+
830+
if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR))
831+
{
832+
assert((gtFlags & GTF_VAR_MULTIREG) != 0);
833+
// The register count for a multireg lclVar requires looking at the LclVarDsc,
834+
// which requires a Compiler instance. The caller must handle this separately.
835+
// The register count for a multireg lclVar requires looking at the LclVarDsc,
836+
// which requires a Compiler instance. The caller must use the GetFieldCount
837+
// method on GenTreeLclVar.
838+
839+
assert(!"MultiRegCount for LclVar");
840+
}
841+
assert(!"GetMultiRegCount called with non-multireg node");
842+
return 1;
843+
}
844+
725845
//---------------------------------------------------------------
726846
// gtGetRegMask: Get the reg mask of the node.
727847
//

src/coreclr/jit/gentree.h

Lines changed: 21 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,10 +1747,10 @@ struct GenTree
17471747
inline bool IsMultiRegLclVar() const;
17481748

17491749
// Returns true if it is a node returning its value in more than one register
1750-
inline bool IsMultiRegNode() const;
1750+
bool IsMultiRegNode() const;
17511751

17521752
// Returns the number of registers defined by a multireg node.
1753-
unsigned GetMultiRegCount();
1753+
unsigned GetMultiRegCount() const;
17541754

17551755
// Returns the regIndex'th register defined by a possibly-multireg node.
17561756
regNumber GetRegByIndex(int regIndex);
@@ -7149,7 +7149,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
71497149
#endif
71507150
}
71517151

7152-
unsigned GetRegCount()
7152+
unsigned GetRegCount() const
71537153
{
71547154
#if FEATURE_MULTIREG_RET
71557155
// We need to return the highest index for which we have a valid register.
@@ -7998,117 +7998,6 @@ inline bool GenTree::IsMultiRegLclVar() const
79987998
return false;
79997999
}
80008000

8001-
//-----------------------------------------------------------------------------------
8002-
// IsMultiRegNode: whether a node returning its value in more than one register
8003-
//
8004-
// Arguments:
8005-
// None
8006-
//
8007-
// Return Value:
8008-
// Returns true if this GenTree is a multi-reg node.
8009-
//
8010-
// Notes:
8011-
// All targets that support multi-reg ops of any kind also support multi-reg return
8012-
// values for calls. Should that change with a future target, this method will need
8013-
// to change accordingly.
8014-
//
8015-
inline bool GenTree::IsMultiRegNode() const
8016-
{
8017-
#if FEATURE_MULTIREG_RET
8018-
if (IsMultiRegCall())
8019-
{
8020-
return true;
8021-
}
8022-
8023-
#if FEATURE_ARG_SPLIT
8024-
if (OperIsPutArgSplit())
8025-
{
8026-
return true;
8027-
}
8028-
#endif
8029-
8030-
#if !defined(TARGET_64BIT)
8031-
if (OperIsMultiRegOp())
8032-
{
8033-
return true;
8034-
}
8035-
#endif
8036-
8037-
if (OperIs(GT_COPY, GT_RELOAD))
8038-
{
8039-
return true;
8040-
}
8041-
#endif // FEATURE_MULTIREG_RET
8042-
#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
8043-
if (OperIs(GT_HWINTRINSIC))
8044-
{
8045-
return (TypeGet() == TYP_STRUCT);
8046-
}
8047-
#endif
8048-
if (IsMultiRegLclVar())
8049-
{
8050-
return true;
8051-
}
8052-
return false;
8053-
}
8054-
//-----------------------------------------------------------------------------------
8055-
// GetMultiRegCount: Return the register count for a multi-reg node.
8056-
//
8057-
// Arguments:
8058-
// None
8059-
//
8060-
// Return Value:
8061-
// Returns the number of registers defined by this node.
8062-
//
8063-
inline unsigned GenTree::GetMultiRegCount()
8064-
{
8065-
#if FEATURE_MULTIREG_RET
8066-
if (IsMultiRegCall())
8067-
{
8068-
return AsCall()->GetReturnTypeDesc()->GetReturnRegCount();
8069-
}
8070-
8071-
#if FEATURE_ARG_SPLIT
8072-
if (OperIsPutArgSplit())
8073-
{
8074-
return AsPutArgSplit()->gtNumRegs;
8075-
}
8076-
#endif
8077-
8078-
#if !defined(TARGET_64BIT)
8079-
if (OperIsMultiRegOp())
8080-
{
8081-
return AsMultiRegOp()->GetRegCount();
8082-
}
8083-
#endif
8084-
8085-
if (OperIs(GT_COPY, GT_RELOAD))
8086-
{
8087-
return AsCopyOrReload()->GetRegCount();
8088-
}
8089-
#endif // FEATURE_MULTIREG_RET
8090-
#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
8091-
if (OperIs(GT_HWINTRINSIC))
8092-
{
8093-
assert(TypeGet() == TYP_STRUCT);
8094-
return 2;
8095-
}
8096-
#endif
8097-
if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR))
8098-
{
8099-
assert((gtFlags & GTF_VAR_MULTIREG) != 0);
8100-
// The register count for a multireg lclVar requires looking at the LclVarDsc,
8101-
// which requires a Compiler instance. The caller must handle this separately.
8102-
// The register count for a multireg lclVar requires looking at the LclVarDsc,
8103-
// which requires a Compiler instance. The caller must use the GetFieldCount
8104-
// method on GenTreeLclVar.
8105-
8106-
assert(!"MultiRegCount for LclVar");
8107-
}
8108-
assert(!"GetMultiRegCount called with non-multireg node");
8109-
return 1;
8110-
}
8111-
81128001
//-----------------------------------------------------------------------------------
81138002
// GetRegByIndex: Get a specific register, based on regIndex, that is produced
81148003
// by this node.
@@ -8156,13 +8045,14 @@ inline regNumber GenTree::GetRegByIndex(int regIndex)
81568045
return AsCopyOrReload()->GetRegNumByIdx(regIndex);
81578046
}
81588047
#endif // FEATURE_MULTIREG_RET
8159-
#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
8048+
#ifdef FEATURE_HW_INTRINSICS
81608049
if (OperIs(GT_HWINTRINSIC))
81618050
{
81628051
assert(regIndex == 1);
8052+
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
81638053
return AsHWIntrinsic()->GetOtherReg();
81648054
}
8165-
#endif
8055+
#endif // FEATURE_HW_INTRINSICS
81668056
if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR))
81678057
{
81688058
return AsLclVar()->GetRegNumByIdx(regIndex);
@@ -8213,15 +8103,26 @@ inline var_types GenTree::GetRegTypeByIndex(int regIndex)
82138103

82148104
#endif // FEATURE_MULTIREG_RET
82158105

8216-
#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
8217-
if (OperIs(GT_HWINTRINSIC))
8106+
if (OperIsHWIntrinsic())
82188107
{
8108+
assert(TypeGet() == TYP_STRUCT);
8109+
#ifdef TARGET_ARM64
8110+
if (AsHWIntrinsic()->GetSimdSize() == 16)
8111+
{
8112+
return TYP_SIMD16;
8113+
}
8114+
else
8115+
{
8116+
assert(AsHWIntrinsic()->GetSimdSize() == 8);
8117+
return TYP_SIMD8;
8118+
}
8119+
#elif defined(TARGET_XARCH)
82198120
// At this time, the only multi-reg HW intrinsics all return the type of their
82208121
// arguments. If this changes, we will need a way to record or determine this.
8221-
assert(TypeGet() == TYP_STRUCT);
82228122
return gtGetOp1()->TypeGet();
8223-
}
82248123
#endif
8124+
}
8125+
82258126
if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR))
82268127
{
82278128
if (TypeGet() == TYP_LONG)

src/coreclr/jit/hwintrinsic.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -770,14 +770,23 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
770770
{
771771
unsigned int sizeBytes;
772772
simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(sig->retTypeSigClass, &sizeBytes);
773-
retType = getSIMDTypeForSize(sizeBytes);
774-
assert(sizeBytes != 0);
775773

776-
// We want to return early here for cases where retType was TYP_STRUCT as per method signature and
777-
// rather than deferring the decision after getting the simdBaseJitType of arg.
778-
if (!isSupportedBaseType(intrinsic, simdBaseJitType))
774+
if (HWIntrinsicInfo::IsMultiReg(intrinsic))
779775
{
780-
return nullptr;
776+
assert(sizeBytes == 0);
777+
}
778+
else
779+
{
780+
assert(sizeBytes != 0);
781+
782+
// We want to return early here for cases where retType was TYP_STRUCT as per method signature and
783+
// rather than deferring the decision after getting the simdBaseJitType of arg.
784+
if (!isSupportedBaseType(intrinsic, simdBaseJitType))
785+
{
786+
return nullptr;
787+
}
788+
789+
retType = getSIMDTypeForSize(sizeBytes);
781790
}
782791
}
783792

@@ -1188,7 +1197,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
11881197
}
11891198

11901199
// This operation contains an implicit indirection
1191-
// it could point into the gloabal heap or
1200+
// it could point into the global heap or
11921201
// it could throw a null reference exception.
11931202
//
11941203
retNode->gtFlags |= (GTF_GLOB_REF | GTF_EXCEPT);

0 commit comments

Comments
 (0)