From 3f5a8083650339336d2431c3376196cdf10e6418 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 12 Sep 2019 14:10:50 +0000 Subject: [PATCH] [ConstProp] allow folding for fma that produces NaN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- llvm/include/llvm/ADT/APFloat.h | 5 ++++ llvm/lib/Analysis/ConstantFolding.cpp | 10 +++----- llvm/test/Transforms/ConstProp/fma.ll | 37 +++++++++------------------ 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index a9648d35cf5d..1c4969733791 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -192,6 +192,11 @@ struct APFloatBase { /// IEEE-754R 7: Default exception handling. /// /// 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 { opOK = 0x00, opInvalidOp = 0x01, diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 51521955e13a..9c926167ca05 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2243,13 +2243,9 @@ static Constant *ConstantFoldScalarCall3(StringRef Name, case Intrinsic::fma: case Intrinsic::fmuladd: { APFloat V = Op1->getValueAPF(); - APFloat::opStatus s = V.fusedMultiplyAdd(Op2->getValueAPF(), - Op3->getValueAPF(), - APFloat::rmNearestTiesToEven); - if (s != APFloat::opInvalidOp) - return ConstantFP::get(Ty->getContext(), V); - - return nullptr; + V.fusedMultiplyAdd(Op2->getValueAPF(), Op3->getValueAPF(), + APFloat::rmNearestTiesToEven); + return ConstantFP::get(Ty->getContext(), V); } } } diff --git a/llvm/test/Transforms/ConstProp/fma.ll b/llvm/test/Transforms/ConstProp/fma.ll index 7428676ac8d3..9119548a91a7 100644 --- a/llvm/test/Transforms/ConstProp/fma.ll +++ b/llvm/test/Transforms/ConstProp/fma.ll @@ -129,8 +129,7 @@ define double @test_Inf_4() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 7.0, double 0xFFF0000000000000, double 0x7FF0000000000000) ret double %1 @@ -140,8 +139,7 @@ define double @inf_product_opposite_inf_addend_1() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 7.0, double 0x7FF0000000000000, double 0xFFF0000000000000) ret double %1 @@ -151,8 +149,7 @@ define double @inf_product_opposite_inf_addend_2() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 42.0, double 0x7FF0000000000000) ret double %1 @@ -162,8 +159,7 @@ define double @inf_product_opposite_inf_addend_3() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 42.0, double 0xFFF0000000000000) ret double %1 @@ -173,8 +169,7 @@ define double @inf_product_opposite_inf_addend_4() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0.0, double 0xFFF0000000000000, double 42.0) ret double %1 @@ -184,8 +179,7 @@ define double @inf_times_zero_1() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0.0, double 0x7FF0000000000000, double 42.0) ret double %1 @@ -195,8 +189,7 @@ define double @inf_times_zero_2() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 0.0, double 42.0) ret double %1 @@ -206,8 +199,7 @@ define double @inf_times_zero_3() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 0.0, double 42.0) ret double %1 @@ -217,8 +209,7 @@ define double @inf_times_zero_4() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double -0.0, double 0xFFF0000000000000, double 42.0) ret double %1 @@ -228,8 +219,7 @@ define double @inf_times_zero_5() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double -0.0, double 0x7FF0000000000000, double 42.0) ret double %1 @@ -239,8 +229,7 @@ define double @inf_times_zero_6() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double -0.0, double 42.0) ret double %1 @@ -250,10 +239,8 @@ define double @inf_times_zero_7() { define double @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 [[TMP1]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double -0.0, double 42.0) ret double %1 } -