@@ -10818,19 +10818,48 @@ SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
10818
10818
return FastLowered;
10819
10819
10820
10820
SDLoc SL(Op);
10821
- SDValue Src0 = Op.getOperand(0);
10822
- SDValue Src1 = Op.getOperand(1);
10823
-
10824
- SDValue CvtSrc0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src0);
10825
- SDValue CvtSrc1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src1);
10826
-
10827
- SDValue RcpSrc1 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, CvtSrc1);
10828
- SDValue Quot = DAG.getNode(ISD::FMUL, SL, MVT::f32, CvtSrc0, RcpSrc1);
10829
-
10830
- SDValue FPRoundFlag = DAG.getTargetConstant(0, SL, MVT::i32);
10831
- SDValue BestQuot = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot, FPRoundFlag);
10821
+ SDValue LHS = Op.getOperand(0);
10822
+ SDValue RHS = Op.getOperand(1);
10832
10823
10833
- return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, BestQuot, Src1, Src0);
10824
+ // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
10825
+ // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
10826
+ // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
10827
+ // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
10828
+ // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
10829
+ // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
10830
+ // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
10831
+ // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
10832
+ // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
10833
+ // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
10834
+ // q16.u = opx(V_CVT_F16_F32, q32.u);
10835
+ // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
10836
+
10837
+ // We will use ISD::FMA on targets that don't support ISD::FMAD.
10838
+ unsigned FMADOpCode =
10839
+ isOperationLegal(ISD::FMAD, MVT::f32) ? ISD::FMAD : ISD::FMA;
10840
+
10841
+ SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
10842
+ SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
10843
+ SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
10844
+ SDValue Rcp =
10845
+ DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
10846
+ SDValue Quot =
10847
+ DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
10848
+ SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
10849
+ Op->getFlags());
10850
+ Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
10851
+ Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
10852
+ Op->getFlags());
10853
+ SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
10854
+ SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
10855
+ TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
10856
+ DAG.getConstant(0xff800000, SL, MVT::i32));
10857
+ Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
10858
+ Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
10859
+ SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
10860
+ DAG.getConstant(0, SL, MVT::i32));
10861
+ return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
10862
+ Op->getFlags());
10834
10863
}
10835
10864
10836
10865
// Faster 2.5 ULP division that does not support denormals.
0 commit comments