[flang-commits] [flang] d71297c - [flang] Fix SPACING() of very small values

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Wed May 24 08:04:51 PDT 2023


Author: Peter Klausler
Date: 2023-05-24T08:04:39-07:00
New Revision: d71297ce746818aea44a4714cf5c807d4ec2b5e0

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

LOG: [flang] Fix SPACING() of very small values

SPACING() must return TINY() for zero arguments (which we do)
and also for subnormal values smaller than TINY() in absolute value,
which we get wrong.  Fix folding and the runtime.

Differential Revision: https://reviews.llvm.org/D151272

Added: 
    

Modified: 
    flang/lib/Evaluate/real.cpp
    flang/runtime/numeric.cpp
    flang/test/Evaluate/fold-spacing.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp
index b5e92b72f69df..4fecaa1a131f8 100644
--- a/flang/lib/Evaluate/real.cpp
+++ b/flang/lib/Evaluate/real.cpp
@@ -745,12 +745,12 @@ template <typename W, int P> Real<W, P> Real<W, P>::SPACING() const {
     return *this;
   } else if (IsInfinite()) {
     return NotANumber();
-  } else if (IsZero()) {
-    return TINY();
+  } else if (IsZero() || IsSubnormal()) {
+    return TINY(); // mandated by standard
   } else {
     Real result;
     result.Normalize(false, Exponent(), Fraction::MASKR(1));
-    return result;
+    return result.IsZero() ? TINY() : result;
   }
 }
 

diff  --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp
index 7afa5802db049..676008792d8cc 100644
--- a/flang/runtime/numeric.cpp
+++ b/flang/runtime/numeric.cpp
@@ -239,8 +239,9 @@ template <int PREC, typename T> inline T Spacing(T x) {
     // subnormal.
     return std::numeric_limits<T>::min(); // 0 -> TINY(x)
   } else {
-    return std::ldexp(
-        static_cast<T>(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p)
+    T result{
+        std::ldexp(static_cast<T>(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p)
+    return result == 0 ? /*TINY(x)*/ std::numeric_limits<T>::min() : result;
   }
 }
 

diff  --git a/flang/test/Evaluate/fold-spacing.f90 b/flang/test/Evaluate/fold-spacing.f90
index 27834da6c2320..1d7b58081d70f 100644
--- a/flang/test/Evaluate/fold-spacing.f90
+++ b/flang/test/Evaluate/fold-spacing.f90
@@ -7,6 +7,7 @@ module m
   logical, parameter :: test_4 = spacing(0.) == tiny(0.)
   logical, parameter :: test_5 = spacing(tiny(0.)) == 1.e-45
   logical, parameter :: test_6 = spacing(8388608.) == 1.
+  logical, parameter :: test_7 = spacing(spacing(tiny(.0))) == tiny(0.)
   logical, parameter :: test_11 = rrspacing(3.0) == scale(0.75, 24)
   logical, parameter :: test_12 = rrspacing(-3.0) == scale(0.75, 24)
   logical, parameter :: test_13 = rrspacing(3.0d0) == scale(0.75, 53)


        


More information about the flang-commits mailing list