[flang-commits] [flang] 1cff71b - [flang] Fold intrinsic functions SPACING() and RRSPACING()

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon May 9 14:09:39 PDT 2022


Author: Peter Klausler
Date: 2022-05-09T14:09:29-07:00
New Revision: 1cff71b975bf4138604775dd32126bb564704ec7

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

LOG: [flang] Fold intrinsic functions SPACING() and RRSPACING()

The related real number system inquiry functions SPACING()
and RRSPACING() can be folded for constant arguments.
See 16.9.164 & 16.9.180 in Fortran 2018.

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

Added: 
    flang/test/Evaluate/fold-spacing.f90

Modified: 
    flang/include/flang/Evaluate/real.h
    flang/lib/Evaluate/fold-real.cpp
    flang/lib/Evaluate/real.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h
index 2f4f7b2c47757..a590186fad138 100644
--- a/flang/include/flang/Evaluate/real.h
+++ b/flang/include/flang/Evaluate/real.h
@@ -160,6 +160,8 @@ class Real : public common::RealDetails<PREC> {
   static constexpr int RANGE{Details::decimalRange};
   static constexpr int MAXEXPONENT{maxExponent - exponentBias};
   static constexpr int MINEXPONENT{2 - exponentBias};
+  Real RRSPACING() const;
+  Real SPACING() const;
 
   // SCALE(); also known as IEEE_SCALB and (in IEEE-754 '08) ScaleB.
   template <typename INT>

diff  --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp
index e915c55760183..1175cc58b21d7 100644
--- a/flang/lib/Evaluate/fold-real.cpp
+++ b/flang/lib/Evaluate/fold-real.cpp
@@ -190,6 +190,10 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
     if (auto *expr{args[0].value().UnwrapExpr()}) {
       return ToReal<KIND>(context, std::move(*expr));
     }
+  } else if (name == "rrspacing") {
+    return FoldElementalIntrinsic<T, T>(context, std::move(funcRef),
+        ScalarFunc<T, T>(
+            [](const Scalar<T> &x) -> Scalar<T> { return x.RRSPACING(); }));
   } else if (name == "scale") {
     if (const auto *byExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) {
       return common::visit(
@@ -218,6 +222,10 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
   } else if (name == "sign") {
     return FoldElementalIntrinsic<T, T, T>(
         context, std::move(funcRef), &Scalar<T>::SIGN);
+  } else if (name == "spacing") {
+    return FoldElementalIntrinsic<T, T>(context, std::move(funcRef),
+        ScalarFunc<T, T>(
+            [](const Scalar<T> &x) -> Scalar<T> { return x.SPACING(); }));
   } else if (name == "sqrt") {
     return FoldElementalIntrinsic<T, T>(context, std::move(funcRef),
         ScalarFunc<T, T>(
@@ -277,8 +285,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
         }));
   }
   // TODO: dim, dot_product, fraction, matmul,
-  // modulo, norm2, rrspacing,
-  // set_exponent, spacing, transfer,
+  // modulo, norm2, set_exponent, transfer,
   return Expr<T>{std::move(funcRef)};
 }
 

diff  --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp
index b8ce0ff8eae66..2b5e32a2542f1 100644
--- a/flang/lib/Evaluate/real.cpp
+++ b/flang/lib/Evaluate/real.cpp
@@ -686,6 +686,35 @@ llvm::raw_ostream &Real<W, P>::AsFortran(
   return o;
 }
 
+// 16.9.180
+template <typename W, int P> Real<W, P> Real<W, P>::RRSPACING() const {
+  if (IsNotANumber()) {
+    return *this;
+  } else if (IsInfinite()) {
+    return NotANumber();
+  } else {
+    Real result;
+    result.Normalize(false, binaryPrecision + exponentBias - 1, GetFraction());
+    return result;
+  }
+}
+
+// 16.9.180
+template <typename W, int P> Real<W, P> Real<W, P>::SPACING() const {
+  if (IsNotANumber()) {
+    return *this;
+  } else if (IsInfinite()) {
+    return NotANumber();
+  } else if (IsZero()) {
+    return TINY();
+  } else {
+    Real result;
+    result.Normalize(
+        false, Exponent() - binaryPrecision + 1, Fraction::MASKL(1));
+    return result;
+  }
+}
+
 template class Real<Integer<16>, 11>;
 template class Real<Integer<16>, 8>;
 template class Real<Integer<32>, 24>;

diff  --git a/flang/test/Evaluate/fold-spacing.f90 b/flang/test/Evaluate/fold-spacing.f90
new file mode 100644
index 0000000000000..d802f1770666e
--- /dev/null
+++ b/flang/test/Evaluate/fold-spacing.f90
@@ -0,0 +1,12 @@
+! RUN: %python %S/test_folding.py %s %flang_fc1
+! Tests folding of SPACING() and RRSPACING
+module m
+  logical, parameter :: test_1 = spacing(3.0) == scale(1.0, -22)
+  logical, parameter :: test_2 = spacing(-3.0) == scale(1.0, -22)
+  logical, parameter :: test_3 = spacing(3.0d0) == scale(1.0, -51)
+  logical, parameter :: test_4 = spacing(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)
+  logical, parameter :: test_14 = rrspacing(0.) == 0.
+end module


        


More information about the flang-commits mailing list