forked from OSchip/llvm-project
[ConstProp] allow folding for fma that produces NaN
Folding for fma/fmuladd was added here: rL202914 ...and as seen in existing/unchanged tests, that works to propagate NaN if it's already an input, but we should fold an fma() that creates NaN too. From IEEE-754-2008 7.2 "Invalid Operation", there are 2 clauses that apply to fma, so I added tests for those patterns: c) fusedMultiplyAdd: fusedMultiplyAdd(0, ∞, c) or fusedMultiplyAdd(∞, 0, c) unless c is a quiet NaN; if c is a quiet NaN then it is implementation defined whether the invalid operation exception is signaled d) addition or subtraction or fusedMultiplyAdd: magnitude subtraction of infinities, such as: addition(+∞, −∞) Differential Revision: https://reviews.llvm.org/D67446 llvm-svn: 371735
This commit is contained in:
parent
03a111dc46
commit
3f5a808365
|
@ -192,6 +192,11 @@ struct APFloatBase {
|
||||||
/// IEEE-754R 7: Default exception handling.
|
/// IEEE-754R 7: Default exception handling.
|
||||||
///
|
///
|
||||||
/// opUnderflow or opOverflow are always returned or-ed with opInexact.
|
/// opUnderflow or opOverflow are always returned or-ed with opInexact.
|
||||||
|
///
|
||||||
|
/// APFloat models this behavior specified by IEEE-754:
|
||||||
|
/// "For operations producing results in floating-point format, the default
|
||||||
|
/// result of an operation that signals the invalid operation exception
|
||||||
|
/// shall be a quiet NaN."
|
||||||
enum opStatus {
|
enum opStatus {
|
||||||
opOK = 0x00,
|
opOK = 0x00,
|
||||||
opInvalidOp = 0x01,
|
opInvalidOp = 0x01,
|
||||||
|
|
|
@ -2243,13 +2243,9 @@ static Constant *ConstantFoldScalarCall3(StringRef Name,
|
||||||
case Intrinsic::fma:
|
case Intrinsic::fma:
|
||||||
case Intrinsic::fmuladd: {
|
case Intrinsic::fmuladd: {
|
||||||
APFloat V = Op1->getValueAPF();
|
APFloat V = Op1->getValueAPF();
|
||||||
APFloat::opStatus s = V.fusedMultiplyAdd(Op2->getValueAPF(),
|
V.fusedMultiplyAdd(Op2->getValueAPF(), Op3->getValueAPF(),
|
||||||
Op3->getValueAPF(),
|
APFloat::rmNearestTiesToEven);
|
||||||
APFloat::rmNearestTiesToEven);
|
return ConstantFP::get(Ty->getContext(), V);
|
||||||
if (s != APFloat::opInvalidOp)
|
|
||||||
return ConstantFP::get(Ty->getContext(), V);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,8 +129,7 @@ define double @test_Inf_4() {
|
||||||
|
|
||||||
define double @inf_product_opposite_inf_addend_1() {
|
define double @inf_product_opposite_inf_addend_1() {
|
||||||
; CHECK-LABEL: @inf_product_opposite_inf_addend_1(
|
; CHECK-LABEL: @inf_product_opposite_inf_addend_1(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 7.000000e+00, double 0xFFF0000000000000, double 0x7FF0000000000000)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 7.0, double 0xFFF0000000000000, double 0x7FF0000000000000)
|
%1 = call double @llvm.fma.f64(double 7.0, double 0xFFF0000000000000, double 0x7FF0000000000000)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -140,8 +139,7 @@ define double @inf_product_opposite_inf_addend_1() {
|
||||||
|
|
||||||
define double @inf_product_opposite_inf_addend_2() {
|
define double @inf_product_opposite_inf_addend_2() {
|
||||||
; CHECK-LABEL: @inf_product_opposite_inf_addend_2(
|
; CHECK-LABEL: @inf_product_opposite_inf_addend_2(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 7.000000e+00, double 0x7FF0000000000000, double 0xFFF0000000000000)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 7.0, double 0x7FF0000000000000, double 0xFFF0000000000000)
|
%1 = call double @llvm.fma.f64(double 7.0, double 0x7FF0000000000000, double 0xFFF0000000000000)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -151,8 +149,7 @@ define double @inf_product_opposite_inf_addend_2() {
|
||||||
|
|
||||||
define double @inf_product_opposite_inf_addend_3() {
|
define double @inf_product_opposite_inf_addend_3() {
|
||||||
; CHECK-LABEL: @inf_product_opposite_inf_addend_3(
|
; CHECK-LABEL: @inf_product_opposite_inf_addend_3(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0xFFF0000000000000, double 4.200000e+01, double 0x7FF0000000000000)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 42.0, double 0x7FF0000000000000)
|
%1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 42.0, double 0x7FF0000000000000)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -162,8 +159,7 @@ define double @inf_product_opposite_inf_addend_3() {
|
||||||
|
|
||||||
define double @inf_product_opposite_inf_addend_4() {
|
define double @inf_product_opposite_inf_addend_4() {
|
||||||
; CHECK-LABEL: @inf_product_opposite_inf_addend_4(
|
; CHECK-LABEL: @inf_product_opposite_inf_addend_4(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0x7FF0000000000000, double 4.200000e+01, double 0xFFF0000000000000)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 42.0, double 0xFFF0000000000000)
|
%1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 42.0, double 0xFFF0000000000000)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -173,8 +169,7 @@ define double @inf_product_opposite_inf_addend_4() {
|
||||||
|
|
||||||
define double @inf_times_zero_1() {
|
define double @inf_times_zero_1() {
|
||||||
; CHECK-LABEL: @inf_times_zero_1(
|
; CHECK-LABEL: @inf_times_zero_1(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0.000000e+00, double 0xFFF0000000000000, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0.0, double 0xFFF0000000000000, double 42.0)
|
%1 = call double @llvm.fma.f64(double 0.0, double 0xFFF0000000000000, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -184,8 +179,7 @@ define double @inf_times_zero_1() {
|
||||||
|
|
||||||
define double @inf_times_zero_2() {
|
define double @inf_times_zero_2() {
|
||||||
; CHECK-LABEL: @inf_times_zero_2(
|
; CHECK-LABEL: @inf_times_zero_2(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0.000000e+00, double 0x7FF0000000000000, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0.0, double 0x7FF0000000000000, double 42.0)
|
%1 = call double @llvm.fma.f64(double 0.0, double 0x7FF0000000000000, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -195,8 +189,7 @@ define double @inf_times_zero_2() {
|
||||||
|
|
||||||
define double @inf_times_zero_3() {
|
define double @inf_times_zero_3() {
|
||||||
; CHECK-LABEL: @inf_times_zero_3(
|
; CHECK-LABEL: @inf_times_zero_3(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0xFFF0000000000000, double 0.000000e+00, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 0.0, double 42.0)
|
%1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 0.0, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -206,8 +199,7 @@ define double @inf_times_zero_3() {
|
||||||
|
|
||||||
define double @inf_times_zero_4() {
|
define double @inf_times_zero_4() {
|
||||||
; CHECK-LABEL: @inf_times_zero_4(
|
; CHECK-LABEL: @inf_times_zero_4(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0x7FF0000000000000, double 0.000000e+00, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 0.0, double 42.0)
|
%1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 0.0, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -217,8 +209,7 @@ define double @inf_times_zero_4() {
|
||||||
|
|
||||||
define double @inf_times_zero_5() {
|
define double @inf_times_zero_5() {
|
||||||
; CHECK-LABEL: @inf_times_zero_5(
|
; CHECK-LABEL: @inf_times_zero_5(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double -0.000000e+00, double 0xFFF0000000000000, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double -0.0, double 0xFFF0000000000000, double 42.0)
|
%1 = call double @llvm.fma.f64(double -0.0, double 0xFFF0000000000000, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -228,8 +219,7 @@ define double @inf_times_zero_5() {
|
||||||
|
|
||||||
define double @inf_times_zero_6() {
|
define double @inf_times_zero_6() {
|
||||||
; CHECK-LABEL: @inf_times_zero_6(
|
; CHECK-LABEL: @inf_times_zero_6(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double -0.000000e+00, double 0x7FF0000000000000, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double -0.0, double 0x7FF0000000000000, double 42.0)
|
%1 = call double @llvm.fma.f64(double -0.0, double 0x7FF0000000000000, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -239,8 +229,7 @@ define double @inf_times_zero_6() {
|
||||||
|
|
||||||
define double @inf_times_zero_7() {
|
define double @inf_times_zero_7() {
|
||||||
; CHECK-LABEL: @inf_times_zero_7(
|
; CHECK-LABEL: @inf_times_zero_7(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0xFFF0000000000000, double -0.000000e+00, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double -0.0, double 42.0)
|
%1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double -0.0, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
|
@ -250,10 +239,8 @@ define double @inf_times_zero_7() {
|
||||||
|
|
||||||
define double @inf_times_zero_8() {
|
define double @inf_times_zero_8() {
|
||||||
; CHECK-LABEL: @inf_times_zero_8(
|
; CHECK-LABEL: @inf_times_zero_8(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fma.f64(double 0x7FF0000000000000, double -0.000000e+00, double 4.200000e+01)
|
; CHECK-NEXT: ret double 0x7FF8000000000000
|
||||||
; CHECK-NEXT: ret double [[TMP1]]
|
|
||||||
;
|
;
|
||||||
%1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double -0.0, double 42.0)
|
%1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double -0.0, double 42.0)
|
||||||
ret double %1
|
ret double %1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue