Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7036,6 +7036,28 @@ AddToWorklist(RV.getNode()); return DAG.getNode(ISD::FMUL, DL, VT, N0, RV); } + } else if (N1.getOpcode() == ISD::FMUL) { + // Look through an FMUL. Even though this won't remove the FDIV directly, + // it's still worthwhile to get rid of the FSQRT if possible. + SDValue SqrtOp; + SDValue OtherOp; + if (N1.getOperand(0).getOpcode() == ISD::FSQRT) { + SqrtOp = N1.getOperand(0); + OtherOp = N1.getOperand(1); + } else if (N1.getOperand(1).getOpcode() == ISD::FSQRT) { + SqrtOp = N1.getOperand(1); + OtherOp = N1.getOperand(0); + } + if (SqrtOp.getNode()) { + // We found a FSQRT, so try to make this fold: + // x / (y * sqrt(z)) -> x * (rsqrt(z) / y) + if (SDValue RV = BuildRsqrtEstimate(SqrtOp.getOperand(0))) { + AddToWorklist(RV.getNode()); + RV = DAG.getNode(ISD::FDIV, SDLoc(N1), VT, RV, OtherOp); + AddToWorklist(RV.getNode()); + return DAG.getNode(ISD::FMUL, DL, VT, N0, RV); + } + } } // Fold into a reciprocal estimate and multiply instead of a real divide. Index: llvm/trunk/test/CodeGen/PowerPC/recipest.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/recipest.ll +++ llvm/trunk/test/CodeGen/PowerPC/recipest.ll @@ -96,6 +96,34 @@ ; CHECK-SAFE: blr } +; Recognize that this is rsqrt(a) * rcp(b) * c, +; not 1 / ( 1 / sqrt(a)) * rcp(b) * c. +define float @rsqrt_fmul(float %a, float %b, float %c) { + %x = call float @llvm.sqrt.f32(float %a) + %y = fmul float %x, %b + %z = fdiv float %c, %y + ret float %z + +; CHECK: @rsqrt_fmul +; CHECK-DAG: frsqrtes +; CHECK-DAG: fres +; CHECK-DAG: fnmsubs +; CHECK-DAG: fmuls +; CHECK-DAG: fnmsubs +; CHECK-DAG: fmadds +; CHECK-DAG: fmadds +; CHECK: fmuls +; CHECK-NEXT: fmuls +; CHECK-NEXT: fmuls +; CHECK-NEXT: blr + +; CHECK-SAFE: @rsqrt_fmul +; CHECK-SAFE: fsqrts +; CHECK-SAFE: fmuls +; CHECK-SAFE: fdivs +; CHECK-SAFE: blr +} + define <4 x float> @hoo(<4 x float> %a, <4 x float> %b) nounwind { %x = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %b) %r = fdiv <4 x float> %a, %x