Only have codegen turn fdiv by a constant into fmul by the reciprocal

when -ffast-math, i.e. don't just always do it if the reciprocal can
be formed exactly.  There is already an IR level transform that does
that, and it does it more carefully.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154296 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2012-04-08 18:08:12 +00:00
parent f873dde502
commit 3ef3fcfc04
2 changed files with 7 additions and 16 deletions

View File

@ -5725,16 +5725,14 @@ SDValue DAGCombiner::visitFDIV(SDNode *N) {
if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT, N0, N1);
// fold (fdiv X, c2) -> fmul X, 1/c2 if there is no precision loss or if
// losing precision is acceptable.
if (N1CFP && VT != MVT::ppcf128) {
// fold (fdiv X, c2) -> fmul X, 1/c2 if losing precision is acceptable.
if (N1CFP && VT != MVT::ppcf128 && DAG.getTarget().Options.UnsafeFPMath) {
// Compute the reciprocal 1.0 / c2.
APFloat N1APF = N1CFP->getValueAPF();
APFloat Recip(N1APF.getSemantics(), 1); // 1.0
APFloat::opStatus st = Recip.divide(N1APF, APFloat::rmNearestTiesToEven);
// Only do the transform if the reciprocal is not too horrible (eg not NaN).
if (st == APFloat::opOK || (st == APFloat::opInexact &&
DAG.getTarget().Options.UnsafeFPMath))
if (st == APFloat::opOK || st == APFloat::opInexact)
return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0,
DAG.getConstantFP(Recip, VT));
}

View File

@ -1,22 +1,17 @@
; RUN: llc < %s -march=x86-64 | FileCheck %s
; RUN: llc < %s -march=x86-64 -enable-unsafe-fp-math | FileCheck -check-prefix=UNSAFE %s
; RUN: llc < %s -march=x86-64 -enable-unsafe-fp-math | FileCheck %s
define double @exact(double %x) {
; Exact division by a constant always converted to multiplication.
; Exact division by a constant converted to multiplication.
; CHECK: @exact
; CHECK: mulsd
; UNSAFE: @exact
; UNSAFE: mulsd
%div = fdiv double %x, 2.0
ret double %div
}
define double @inexact(double %x) {
; Inexact division by a constant converted to multiplication if unsafe-math.
; Inexact division by a constant converted to multiplication.
; CHECK: @inexact
; CHECK: divsd
; UNSAFE: @inexact
; UNSAFE: mulsd
; CHECK: mulsd
%div = fdiv double %x, 0x41DFFFFFFFC00000
ret double %div
}
@ -25,8 +20,6 @@ define double @funky(double %x) {
; No conversion to multiplication if too funky.
; CHECK: @funky
; CHECK: divsd
; UNSAFE: @funky
; UNSAFE: divsd
%div = fdiv double %x, 0.0
ret double %div
}