[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