[flang-commits] [flang] 29fa451 - [flang] Add isnan() extension intrinsic function, with folding

peter klausler via flang-commits flang-commits at lists.llvm.org
Wed Nov 11 11:41:22 PST 2020


Author: peter klausler
Date: 2020-11-11T11:40:57-08:00
New Revision: 29fa4518703e5770b3912d4b8143e1918ac60415

URL: https://github.com/llvm/llvm-project/commit/29fa4518703e5770b3912d4b8143e1918ac60415
DIFF: https://github.com/llvm/llvm-project/commit/29fa4518703e5770b3912d4b8143e1918ac60415.diff

LOG: [flang] Add isnan() extension intrinsic function, with folding

It's nonstandard, but commonly implemented.

Differential revision: https://reviews.llvm.org/D91213

Added: 
    flang/test/Evaluate/folding14.f90

Modified: 
    flang/docs/Extensions.md
    flang/include/flang/Evaluate/real.h
    flang/lib/Evaluate/common.cpp
    flang/lib/Evaluate/fold-logical.cpp
    flang/lib/Evaluate/intrinsics.cpp
    flang/test/Evaluate/folding03.f90
    flang/test/Evaluate/folding04.f90

Removed: 
    


################################################################################
diff  --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 1c85c3f42d1b..d0b24969b41b 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -129,6 +129,7 @@ accepted if enabled by command-line options.
 * A `RETURN` statement may appear in a main program.
 * DATA statement initialization is allowed for procedure pointers outside
   structure constructors.
+* Nonstandard intrinsic functions: ISNAN
 
 ### Extensions supported when enabled by options
 

diff  --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h
index 3af11d2058fd..8ceb4639aa93 100644
--- a/flang/include/flang/Evaluate/real.h
+++ b/flang/include/flang/Evaluate/real.h
@@ -247,12 +247,17 @@ class Real : public common::RealDetails<PREC> {
   template <typename A>
   static ValueWithRealFlags<Real> Convert(
       const A &x, Rounding rounding = defaultRounding) {
+    ValueWithRealFlags<Real> result;
+    if (x.IsNotANumber()) {
+      result.flags.set(RealFlag::InvalidArgument);
+      result.value = NotANumber();
+      return result;
+    }
     bool isNegative{x.IsNegative()};
     A absX{x};
     if (isNegative) {
       absX = x.Negate();
     }
-    ValueWithRealFlags<Real> result;
     int exponent{exponentBias + x.UnbiasedExponent()};
     int bitsLost{A::binaryPrecision - binaryPrecision};
     if (exponent < 1) {

diff  --git a/flang/lib/Evaluate/common.cpp b/flang/lib/Evaluate/common.cpp
index cdfa9989ba76..0cdd181d3961 100644
--- a/flang/lib/Evaluate/common.cpp
+++ b/flang/lib/Evaluate/common.cpp
@@ -19,7 +19,11 @@ void RealFlagWarnings(
     context.messages().Say("overflow on %s"_en_US, operation);
   }
   if (flags.test(RealFlag::DivideByZero)) {
-    context.messages().Say("division by zero on %s"_en_US, operation);
+    if (std::strcmp(operation, "division") == 0) {
+      context.messages().Say("division by zero"_en_US);
+    } else {
+      context.messages().Say("division on %s"_en_US);
+    }
   }
   if (flags.test(RealFlag::InvalidArgument)) {
     context.messages().Say("invalid argument on %s"_en_US, operation);

diff  --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index 48f82125e2eb..bf283c4f9206 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -89,6 +89,15 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
             [&fptr](const Scalar<LargestInt> &i, const Scalar<LargestInt> &j) {
               return Scalar<T>{std::invoke(fptr, i, j)};
             }));
+  } else if (name == "isnan") {
+    // A warning about an invalid argument is discarded from converting
+    // the argument of isnan().
+    auto restorer{context.messages().DiscardMessages()};
+    using DefaultReal = Type<TypeCategory::Real, 4>;
+    return FoldElementalIntrinsic<T, DefaultReal>(context, std::move(funcRef),
+        ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) {
+          return Scalar<T>{x.IsNotANumber()};
+        }));
   } else if (name == "is_contiguous") {
     if (args.at(0)) {
       if (auto *expr{args[0]->UnwrapExpr()}) {

diff  --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 60e8eee2e243..2d8ad85a1e59 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -476,6 +476,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
         {{"i", SameInt}, {"shift", AnyInt},
             {"size", AnyInt, Rank::elemental, Optionality::optional}},
         SameInt},
+    {"isnan", {{"a", AnyFloating}}, DefaultLogical},
     {"is_contiguous", {{"array", Addressable, Rank::anyOrAssumedRank}},
         DefaultLogical, Rank::elemental, IntrinsicClass::inquiryFunction},
     {"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
@@ -744,7 +745,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
 //  INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF,
 //  MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR
 //  IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE,
-//  EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC
+//  EOF, FP_CLASS, INT_PTR_KIND, MALLOC
 //  probably more (these are PGI + Intel, possibly incomplete)
 // TODO: Optionally warn on use of non-standard intrinsics:
 //  LOC, probably others

diff  --git a/flang/test/Evaluate/folding03.f90 b/flang/test/Evaluate/folding03.f90
index c50390036deb..22377d0b1df7 100644
--- a/flang/test/Evaluate/folding03.f90
+++ b/flang/test/Evaluate/folding03.f90
@@ -79,9 +79,9 @@ module real_tests
   !WARN: invalid argument on division
   real(4), parameter :: r4_nan = 0._4/0._4
   TEST_ISNAN(r4_nan)
-  !WARN: division by zero on division
+  !WARN: division by zero
   real(4), parameter :: r4_pinf = 1._4/0._4
-  !WARN: division by zero on division
+  !WARN: division by zero
   real(4), parameter :: r4_ninf = -1._4/0._4
 
   logical, parameter :: test_r4_nan_parentheses1 = .NOT.(((r4_nan)).EQ.r4_nan)

diff  --git a/flang/test/Evaluate/folding04.f90 b/flang/test/Evaluate/folding04.f90
index 45e48c85ddeb..187822e5d230 100644
--- a/flang/test/Evaluate/folding04.f90
+++ b/flang/test/Evaluate/folding04.f90
@@ -12,9 +12,9 @@ module real_tests
   real(4), parameter :: r4_nmax = -3.4028235E38
   !WARN: invalid argument on division
   real(4), parameter :: r4_nan = 0._4/0._4
-  !WARN: division by zero on division
+  !WARN: division by zero
   real(4), parameter :: r4_pinf = 1._4/0._4
-  !WARN: division by zero on division
+  !WARN: division by zero
   real(4), parameter :: r4_ninf = -1._4/0._4
 
   !WARN: invalid argument on intrinsic function

diff  --git a/flang/test/Evaluate/folding14.f90 b/flang/test/Evaluate/folding14.f90
new file mode 100644
index 000000000000..106b8ed9e27f
--- /dev/null
+++ b/flang/test/Evaluate/folding14.f90
@@ -0,0 +1,18 @@
+! RUN: %S/test_folding.sh %s %t %f18
+! Test folding of isnan() extension
+module m1
+  logical, parameter :: results(*) = isnan([ &
+    0., &
+    -0., &
+!WARN: division by zero
+    1./0., &
+!WARN: invalid argument on division
+    0./0., &
+    real(z'7ff80001',kind=4), &
+    real(z'fff80001',kind=4), &
+    real(z'7ffc0000',kind=4), &
+    real(z'7ffe0000',kind=4) ])
+  logical, parameter :: expected(*) = [ &
+    .false., .false., .false., .true., .true., .true., .true., .true. ]
+  logical, parameter :: test_isnan = all(results .eqv. expected)
+end module


        


More information about the flang-commits mailing list