@@ -4146,6 +4146,13 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
4146
4146
break;
4147
4147
}
4148
4148
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
+
4149
4156
case NI_System_Array_Clone:
4150
4157
case NI_System_Collections_Generic_Comparer_get_Default:
4151
4158
case NI_System_Collections_Generic_EqualityComparer_get_Default:
@@ -7413,13 +7420,15 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
7413
7420
// instructions to directly compute round/ceiling/floor/truncate.
7414
7421
7415
7422
case NI_System_Math_Abs:
7423
+ case NI_System_Math_ReciprocalEstimate:
7424
+ case NI_System_Math_ReciprocalSqrtEstimate:
7416
7425
case NI_System_Math_Sqrt:
7417
7426
return true;
7418
7427
7419
7428
case NI_System_Math_Ceiling:
7420
7429
case NI_System_Math_Floor:
7421
- case NI_System_Math_Truncate:
7422
7430
case NI_System_Math_Round:
7431
+ case NI_System_Math_Truncate:
7423
7432
return compOpportunisticallyDependsOn(InstructionSet_SSE41);
7424
7433
7425
7434
case NI_System_Math_FusedMultiplyAdd:
@@ -7434,11 +7443,13 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
7434
7443
case NI_System_Math_Abs:
7435
7444
case NI_System_Math_Ceiling:
7436
7445
case NI_System_Math_Floor:
7437
- case NI_System_Math_Truncate:
7438
- case NI_System_Math_Round:
7439
- case NI_System_Math_Sqrt:
7440
7446
case NI_System_Math_Max:
7441
7447
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:
7442
7453
return true;
7443
7454
7444
7455
case NI_System_Math_FusedMultiplyAdd:
@@ -7513,6 +7524,8 @@ bool Compiler::IsMathIntrinsic(NamedIntrinsic intrinsicName)
7513
7524
case NI_System_Math_MinMagnitudeNumber:
7514
7525
case NI_System_Math_MinNumber:
7515
7526
case NI_System_Math_Pow:
7527
+ case NI_System_Math_ReciprocalEstimate:
7528
+ case NI_System_Math_ReciprocalSqrtEstimate:
7516
7529
case NI_System_Math_Round:
7517
7530
case NI_System_Math_Sin:
7518
7531
case NI_System_Math_Sinh:
@@ -8730,6 +8743,121 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
8730
8743
}
8731
8744
}
8732
8745
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
+
8733
8861
GenTree* Compiler::impMathIntrinsic(CORINFO_METHOD_HANDLE method,
8734
8862
CORINFO_SIG_INFO* sig,
8735
8863
var_types callType,
@@ -10339,7 +10467,20 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL
10339
10467
10340
10468
case 'R':
10341
10469
{
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)
10343
10484
{
10344
10485
result = NI_System_Math_Round;
10345
10486
}
0 commit comments