@@ -4146,6 +4146,13 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
41464146 break ;
41474147 }
41484148
4149+ case NI_System_Math_ReciprocalEstimate:
4150+ case NI_System_Math_ReciprocalSqrtEstimate:
4151+ {
4152+ retNode = impEstimateIntrinsic (method, sig, callJitType, ni, tailCall);
4153+ break ;
4154+ }
4155+
41494156 case NI_System_Array_Clone:
41504157 case NI_System_Collections_Generic_Comparer_get_Default:
41514158 case NI_System_Collections_Generic_EqualityComparer_get_Default:
@@ -7413,13 +7420,15 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
74137420 // instructions to directly compute round/ceiling/floor/truncate.
74147421
74157422 case NI_System_Math_Abs:
7423+ case NI_System_Math_ReciprocalEstimate:
7424+ case NI_System_Math_ReciprocalSqrtEstimate:
74167425 case NI_System_Math_Sqrt:
74177426 return true ;
74187427
74197428 case NI_System_Math_Ceiling:
74207429 case NI_System_Math_Floor:
7421- case NI_System_Math_Truncate:
74227430 case NI_System_Math_Round:
7431+ case NI_System_Math_Truncate:
74237432 return compOpportunisticallyDependsOn (InstructionSet_SSE41);
74247433
74257434 case NI_System_Math_FusedMultiplyAdd:
@@ -7434,11 +7443,13 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
74347443 case NI_System_Math_Abs:
74357444 case NI_System_Math_Ceiling:
74367445 case NI_System_Math_Floor:
7437- case NI_System_Math_Truncate:
7438- case NI_System_Math_Round:
7439- case NI_System_Math_Sqrt:
74407446 case NI_System_Math_Max:
74417447 case NI_System_Math_Min:
7448+ case NI_System_Math_ReciprocalEstimate:
7449+ case NI_System_Math_ReciprocalSqrtEstimate:
7450+ case NI_System_Math_Round:
7451+ case NI_System_Math_Sqrt:
7452+ case NI_System_Math_Truncate:
74427453 return true ;
74437454
74447455 case NI_System_Math_FusedMultiplyAdd:
@@ -7513,6 +7524,8 @@ bool Compiler::IsMathIntrinsic(NamedIntrinsic intrinsicName)
75137524 case NI_System_Math_MinMagnitudeNumber:
75147525 case NI_System_Math_MinNumber:
75157526 case NI_System_Math_Pow:
7527+ case NI_System_Math_ReciprocalEstimate:
7528+ case NI_System_Math_ReciprocalSqrtEstimate:
75167529 case NI_System_Math_Round:
75177530 case NI_System_Math_Sin:
75187531 case NI_System_Math_Sinh:
@@ -8730,6 +8743,121 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
87308743 }
87318744}
87328745
8746+ // ------------------------------------------------------------------------
8747+ // impMinMaxIntrinsic: Imports a min or max intrinsic
8748+ //
8749+ // Arguments:
8750+ // method - The handle of the method being imported
8751+ // callType - The underlying type for the call
8752+ // intrinsicName - The intrinsic being imported
8753+ // tailCall - true if the method is a tail call; otherwise false
8754+ // isMax - true if the intrinsic computes the max; false for the min
8755+ // isMagnitude - true if the intrinsic compares using the absolute value of the inputs
8756+ // isNumber - true if the intrinsic propagates the number; false for NaN
8757+ //
8758+ GenTree* Compiler::impEstimateIntrinsic (CORINFO_METHOD_HANDLE method,
8759+ CORINFO_SIG_INFO* sig,
8760+ CorInfoType callJitType,
8761+ NamedIntrinsic intrinsicName,
8762+ bool tailCall)
8763+ {
8764+ var_types callType = JITtype2varType (callJitType);
8765+
8766+ assert (varTypeIsFloating (callType));
8767+ assert (sig->numArgs == 1 );
8768+
8769+ #if defined(FEATURE_HW_INTRINSICS)
8770+ // We use compExactlyDependsOn since these are estimate APIs where
8771+ // the behavior is explicitly allowed to differ across machines and
8772+ // we want to ensure that it gets marked as such in R2R.
8773+
8774+ var_types simdType = TYP_UNKNOWN;
8775+ NamedIntrinsic intrinsicId = NI_Illegal;
8776+
8777+ switch (intrinsicName)
8778+ {
8779+ case NI_System_Math_ReciprocalEstimate:
8780+ {
8781+ #if defined(TARGET_XARCH)
8782+ if (compExactlyDependsOn (InstructionSet_AVX512F))
8783+ {
8784+ simdType = TYP_SIMD16;
8785+ intrinsicId = NI_AVX512F_Reciprocal14Scalar;
8786+ }
8787+ else if ((callType == TYP_FLOAT) && compExactlyDependsOn (InstructionSet_SSE))
8788+ {
8789+ simdType = TYP_SIMD16;
8790+ intrinsicId = NI_SSE_ReciprocalScalar;
8791+ }
8792+ #elif defined(TARGET_ARM64)
8793+ if (compExactlyDependsOn (InstructionSet_AdvSimd_Arm64))
8794+ {
8795+ simdType = TYP_SIMD8;
8796+ intrinsicId = NI_AdvSimd_Arm64_ReciprocalEstimateScalar;
8797+ }
8798+ #endif // TARGET_ARM64
8799+ break ;
8800+ }
8801+
8802+ case NI_System_Math_ReciprocalSqrtEstimate:
8803+ {
8804+ #if defined(TARGET_XARCH)
8805+ if (compExactlyDependsOn (InstructionSet_AVX512F))
8806+ {
8807+ simdType = TYP_SIMD16;
8808+ intrinsicId = NI_AVX512F_ReciprocalSqrt14Scalar;
8809+ }
8810+ else if ((callType == TYP_FLOAT) && compExactlyDependsOn (InstructionSet_SSE))
8811+ {
8812+ simdType = TYP_SIMD16;
8813+ intrinsicId = NI_SSE_ReciprocalSqrtScalar;
8814+ }
8815+ #elif defined(TARGET_ARM64)
8816+ if (compExactlyDependsOn (InstructionSet_AdvSimd_Arm64))
8817+ {
8818+ simdType = TYP_SIMD8;
8819+ intrinsicId = NI_AdvSimd_Arm64_ReciprocalSquareRootEstimateScalar;
8820+ }
8821+ #endif // TARGET_ARM64
8822+ break ;
8823+ }
8824+
8825+ default :
8826+ {
8827+ unreached ();
8828+ }
8829+ }
8830+
8831+ if (intrinsicId != NI_Illegal)
8832+ {
8833+ unsigned simdSize = 0 ;
8834+
8835+ if (simdType == TYP_SIMD8)
8836+ {
8837+ simdSize = 8 ;
8838+ }
8839+ else
8840+ {
8841+ assert (simdType == TYP_SIMD16);
8842+ simdSize = 16 ;
8843+ }
8844+
8845+ GenTree* op1 = impPopStack ().val ;
8846+
8847+ op1 = gtNewSimdCreateScalarUnsafeNode (simdType, op1, callJitType, simdSize);
8848+ op1 = gtNewSimdHWIntrinsicNode (simdType, op1, intrinsicId, callJitType, simdSize);
8849+
8850+ return gtNewSimdToScalarNode (callType, op1, callJitType, simdSize);
8851+ }
8852+ #endif // FEATURE_HW_INTRINSICS
8853+
8854+ // TODO-CQ: Returning this as an intrinsic blocks inlining and is undesirable
8855+ // return impMathIntrinsic(method, sig, callType, intrinsicName, tailCall);
8856+
8857+ return nullptr ;
8858+ }
8859+
8860+
87338861GenTree* Compiler::impMathIntrinsic (CORINFO_METHOD_HANDLE method,
87348862 CORINFO_SIG_INFO* sig,
87358863 var_types callType,
@@ -10339,7 +10467,20 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL
1033910467
1034010468 case ' R' :
1034110469 {
10342- if (strcmp (methodName, " Round" ) == 0 )
10470+ if (strncmp (methodName, " Reciprocal" , 10 ) == 0 )
10471+ {
10472+ methodName += 10 ;
10473+
10474+ if (strcmp (methodName, " Estimate" ) == 0 )
10475+ {
10476+ result = NI_System_Math_ReciprocalEstimate;
10477+ }
10478+ else if (strcmp (methodName, " SqrtEstimate" ) == 0 )
10479+ {
10480+ result = NI_System_Math_ReciprocalSqrtEstimate;
10481+ }
10482+ }
10483+ else if (strcmp (methodName, " Round" ) == 0 )
1034310484 {
1034410485 result = NI_System_Math_Round;
1034510486 }
0 commit comments