[flang-commits] [flang] 8985cfd - [flang][runtime] Fixed identity value for REAL(16) == __float128.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Wed Sep 28 10:13:22 PDT 2022


Author: Slava Zakharin
Date: 2022-09-28T10:11:37-07:00
New Revision: 8985cfd93980a1d7d92699bfefce34e7bf5887fb

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

LOG: [flang][runtime] Fixed identity value for REAL(16) == __float128.

std::numeric_limits<__float128>::max/lowest return 0.0, so recreate
value of FLT128_MAX ourselves to avoid using quadmath.h's FLT128_MAX
that is currently causes warnings with GCC -Wpedantic.

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

Added: 
    

Modified: 
    flang/runtime/extrema.cpp
    flang/unittests/Runtime/Reduction.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/extrema.cpp b/flang/runtime/extrema.cpp
index f96a91c059512..a1413b4734446 100644
--- a/flang/runtime/extrema.cpp
+++ b/flang/runtime/extrema.cpp
@@ -301,7 +301,8 @@ void RTNAME(MinlocDim)(Descriptor &result, const Descriptor &x, int kind,
 
 // MAXVAL and MINVAL
 
-template <TypeCategory CAT, int KIND, bool IS_MAXVAL> struct MaxOrMinIdentity {
+template <TypeCategory CAT, int KIND, bool IS_MAXVAL, typename Enable = void>
+struct MaxOrMinIdentity {
   using Type = CppTypeFor<CAT, KIND>;
   static constexpr Type Value() {
     return IS_MAXVAL ? std::numeric_limits<Type>::lowest()
@@ -318,6 +319,44 @@ struct MaxOrMinIdentity<TypeCategory::Integer, 16, IS_MAXVAL> {
   }
 };
 
+#if HAS_FLOAT128
+// std::numeric_limits<> may not support __float128.
+//
+// Usage of GCC quadmath.h's FLT128_MAX is complicated by the fact that
+// even GCC complains about 'Q' literal suffix under -Wpedantic.
+// We just recreate FLT128_MAX ourselves.
+//
+// This specialization must engage only when
+// CppTypeFor<TypeCategory::Real, 16> is __float128.
+template <bool IS_MAXVAL>
+struct MaxOrMinIdentity<TypeCategory::Real, 16, IS_MAXVAL,
+    typename std::enable_if_t<
+        std::is_same_v<CppTypeFor<TypeCategory::Real, 16>, __float128>>> {
+  using Type = __float128;
+  static Type Value() {
+    // Create a buffer to store binary representation of __float128 constant.
+    constexpr std::size_t alignment =
+        std::max(alignof(Type), alignof(std::uint64_t));
+    alignas(alignment) char data[sizeof(Type)];
+
+    // First, verify that our interpretation of __float128 format is correct,
+    // e.g. by checking at least one known constant.
+    *reinterpret_cast<Type *>(data) = Type(1.0);
+    if (*reinterpret_cast<std::uint64_t *>(data) != 0 ||
+        *(reinterpret_cast<std::uint64_t *>(data) + 1) != 0x3FFF000000000000) {
+      Terminator terminator{__FILE__, __LINE__};
+      terminator.Crash("not yet implemented: no full support for __float128");
+    }
+
+    // Recreate FLT128_MAX.
+    *reinterpret_cast<std::uint64_t *>(data) = 0xFFFFFFFFFFFFFFFF;
+    *(reinterpret_cast<std::uint64_t *>(data) + 1) = 0x7FFEFFFFFFFFFFFF;
+    Type max = *reinterpret_cast<Type *>(data);
+    return IS_MAXVAL ? -max : max;
+  }
+};
+#endif // HAS_FLOAT128
+
 template <TypeCategory CAT, int KIND, bool IS_MAXVAL>
 class NumericExtremumAccumulator {
 public:

diff  --git a/flang/unittests/Runtime/Reduction.cpp b/flang/unittests/Runtime/Reduction.cpp
index a9207521dfe2d..6f499b7203438 100644
--- a/flang/unittests/Runtime/Reduction.cpp
+++ b/flang/unittests/Runtime/Reduction.cpp
@@ -616,3 +616,20 @@ TEST(Reductions, DotProduct) {
   EXPECT_FALSE(RTNAME(DotProductLogical)(
       *logicalVector2, *logicalVector1, __FILE__, __LINE__));
 }
+
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+TEST(Reductions, ExtremaReal16) {
+  // The identity value for Min/Maxval for REAL(16) was mistakenly
+  // set to 0.0.
+  using ElemType = CppTypeFor<TypeCategory::Real, 16>;
+  std::vector<int> shape{3};
+  //   1.0  2.0  3.0
+  std::vector<ElemType> rawMinData{1.0, 2.0, 3.0};
+  auto minArray{MakeArray<TypeCategory::Real, 16>(shape, rawMinData)};
+  EXPECT_EQ(RTNAME(MinvalReal16)(*minArray, __FILE__, __LINE__), 1.0);
+  //   -1.0  -2.0  -3.0
+  std::vector<ElemType> rawMaxData{-1.0, -2.0, -3.0};
+  auto maxArray{MakeArray<TypeCategory::Real, 16>(shape, rawMaxData)};
+  EXPECT_EQ(RTNAME(MaxvalReal16)(*maxArray, __FILE__, __LINE__), -1.0);
+}
+#endif // LDBL_MANT_DIG == 113 || HAS_FLOAT128


        


More information about the flang-commits mailing list