[InstSimplify] Add self-fdiv identities for -ffinite-math-only.

When NaNs and Infs are ignored we can fold
 X /  X -> 1.0
-X /  X -> -1.0
 X / -X -> -1.0

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239701 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2015-06-14 18:53:58 +00:00
parent 17ae2138b0
commit f3e82660de
2 changed files with 92 additions and 0 deletions

View File

@ -1126,6 +1126,21 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op0, m_AnyZero()))
return Op0;
if (FMF.noNaNs() && FMF.noInfs()) {
// X / X -> 1.0 iff NaNs and infinities are ignored.
if (Op0 == Op1)
return ConstantFP::get(Op0->getType(), 1.0);
// -X / X -> -1.0 and
// X / -X -> -1.0 iff NaNs and infinities are ignored.
// We can ignore signed zeros because +-0.0/+-0.0 is NaN and ignored.
if ((BinaryOperator::isFNeg(Op0, /*IgnoreZeroSign=*/true) &&
BinaryOperator::getFNegArgument(Op0) == Op1) ||
(BinaryOperator::isFNeg(Op1, /*IgnoreZeroSign=*/true) &&
BinaryOperator::getFNegArgument(Op1) == Op0))
return ConstantFP::get(Op0->getType(), -1.0);
}
return nullptr;
}

View File

@ -114,3 +114,80 @@ define double @fdiv_zero_by_x(double %X) {
ret double %r
; CHECK: ret double 0
}
define float @fdiv_self(float %f) {
%div = fdiv nnan ninf float %f, %f
ret float %div
; CHECK-LABEL: fdiv_self
; CHECK: ret float 1.000000e+00
}
define float @fdiv_self_invalid1(float %f) {
%div = fdiv ninf float %f, %f
ret float %div
; CHECK-LABEL: fdiv_self_invalid1
; CHECK: %div = fdiv ninf float %f, %f
; CHECK-NEXT: ret float %div
}
define float @fdiv_self_invalid2(float %f) {
%div = fdiv nnan float %f, %f
ret float %div
; CHECK-LABEL: fdiv_self_invalid2
; CHECK: %div = fdiv nnan float %f, %f
; CHECK-NEXT: ret float %div
}
define float @fdiv_self_invalid3(float %f) {
%div = fdiv float %f, %f
ret float %div
; CHECK-LABEL: fdiv_self_invalid3
; CHECK: %div = fdiv float %f, %f
; CHECK-NEXT: ret float %div
}
define float @fdiv_neg(float %f) {
%neg = fsub fast float -0.000000e+00, %f
%div = fdiv nnan ninf float %neg, %f
ret float %div
; CHECK-LABEL: fdiv_neg
; CHECK: ret float -1.000000e+00
}
define float @fdiv_neg_invalid1(float %f) {
%neg = fsub fast float -0.000000e+00, %f
%div = fdiv ninf float %neg, %f
ret float %div
; CHECK-LABEL: fdiv_neg_invalid1
; CHECK: %neg = fsub fast float -0.000000e+00, %f
; CHECK-NEXT: %div = fdiv ninf float %neg, %f
; CHECK-NEXT: ret float %div
}
define float @fdiv_neg_invalid2(float %f) {
%neg = fsub fast float -0.000000e+00, %f
%div = fdiv nnan float %neg, %f
ret float %div
; CHECK-LABEL: fdiv_neg_invalid2
; CHECK: %neg = fsub fast float -0.000000e+00, %f
; CHECK-NEXT: %div = fdiv nnan float %neg, %f
; CHECK-NEXT: ret float %div
}
define float @fdiv_neg_invalid3(float %f) {
%neg = fsub fast float -0.000000e+00, %f
%div = fdiv float %neg, %f
ret float %div
; CHECK-LABEL: fdiv_neg_invalid3
; CHECK: %neg = fsub fast float -0.000000e+00, %f
; CHECK-NEXT: %div = fdiv float %neg, %f
; CHECK-NEXT: ret float %div
}
define float @fdiv_neg_swapped(float %f) {
%neg = fsub float 0.000000e+00, %f
%div = fdiv nnan ninf float %f, %neg
ret float %div
; CHECK-LABEL: fdiv_neg_swapped
; CHECK: ret float -1.000000e+00
}