[libc] [llvm] [APFloat] Add exp function for APFloat::IEEESsingle using expf implementation from LLVM libc. (PR #143959)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 13 08:37:39 PDT 2025


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/143959

>From aeaac932cde03103ba4831dfd54d943098fad716 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 12 Jun 2025 19:53:28 +0000
Subject: [PATCH 1/5] [APFloat] Add exp function for APFloat::IEEESsingle using
 expf implementation from LLVM libc.

---
 llvm/CMakeLists.txt                          | 11 +++++++
 llvm/include/llvm/ADT/APFloat.h              |  5 +++
 llvm/include/llvm/Config/llvm-config.h.cmake |  3 ++
 llvm/lib/Support/APFloat.cpp                 | 34 ++++++++++++++++++++
 llvm/lib/Support/CMakeLists.txt              |  6 ++++
 llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp    |  2 +-
 llvm/unittests/ADT/APFloatTest.cpp           | 19 +++++++++++
 7 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 0849bec26d56a..4128cceaf33fa 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -644,6 +644,17 @@ endif()
 
 set(LLVM_ENABLE_Z3_SOLVER_DEFAULT "${Z3_FOUND}")
 
+set(LLVM_INTEGRATE_LIBC "OFF" CACHE STRING "Use LLVM libc codes directly if available.")
+
+if(LLVM_INTEGRATE_LIBC)
+  message(STATUS "LLVM_INTEGRATE_LIBC is ${LLVM_INTEGRATE_LIBC}")
+  include(FindLibcCommonUtils)
+  if(NOT TARGET llvm-libc-common-utilities)
+    message(STATUS "LLVM_INTEGRATE_LIBC is set but cannot find LLVM libc at ${libc_path}.")
+    set(LLVM_INTEGRATE_LIBC OFF)
+  endif()
+endif()
+
 
 if( LLVM_TARGETS_TO_BUILD STREQUAL "all" )
   set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} )
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 13df838da3dad..6f6dd3c014584 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1522,6 +1522,7 @@ class APFloat : public APFloatBase {
   friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
   friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
   friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
+  friend APFloat exp(const APFloat &X, roundingMode RM);
   friend IEEEFloat;
   friend DoubleAPFloat;
 };
@@ -1657,6 +1658,10 @@ inline APFloat maximumnum(const APFloat &A, const APFloat &B) {
   return A < B ? B : A;
 }
 
+/// Implement IEEE 754-2019 exp functions.
+LLVM_READONLY
+APFloat exp(const APFloat &X, RoundingMode RM);
+
 inline raw_ostream &operator<<(raw_ostream &OS, const APFloat &V) {
   V.print(OS);
   return OS;
diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake
index 6d3c37cc8b194..30c4ed6fffc74 100644
--- a/llvm/include/llvm/Config/llvm-config.h.cmake
+++ b/llvm/include/llvm/Config/llvm-config.h.cmake
@@ -137,4 +137,7 @@
    coverage bugs, and to 0 otherwise. */
 #cmakedefine01 LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
 
+/* Define if LLVM and clang uses LLVM libc for math computations. */
+#cmakedefine LLVM_INTEGRATE_LIBC
+
 #endif
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 5e0b29ffb2590..150853743540d 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -28,6 +28,11 @@
 #include <cstring>
 #include <limits.h>
 
+#ifdef LLVM_INTEGRATE_LIBC
+// Shared headers from LLVM libc
+#include "shared/math.h"
+#endif // LLVM_INTEGRATE_LIBC
+
 #define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL)                             \
   do {                                                                         \
     if (usesLayout<IEEEFloat>(getSemantics()))                                 \
@@ -5601,6 +5606,35 @@ float APFloat::convertToFloat() const {
   return Temp.getIEEE().convertToFloat();
 }
 
+#ifdef LLVM_INTEGRATE_LIBC
+APFloat exp(const APFloat &X, RoundingMode rounding_mode) {
+  assert((&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) &&
+         "Float semantics is not IEEEsingle");
+  if (&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) {
+    int current_rounding_mode = fegetround();
+    switch (rounding_mode) {
+    case APFloat::rmNearestTiesToEven:
+      fesetround(FE_TONEAREST);
+      break;
+    case APFloat::rmTowardPositive:
+      fesetround(FE_UPWARD);
+      break;
+    case APFloat::rmTowardNegative:
+      fesetround(FE_DOWNWARD);
+      break;
+    case APFloat::rmTowardZero:
+      fesetround(FE_TOWARDZERO);
+      break;
+    default:
+    }
+    float result = LIBC_NAMESPACE::shared::expf(X.convertToFloat());
+    fesetround(current_rounding_mode);
+    return APFloat(result);
+  }
+  llvm_unreachable("Unexpected semantics");
+}
+#endif // LLVM_INTEGRATE_LIBC
+
 } // namespace llvm
 
 #undef APFLOAT_DISPATCH_ON_SEMANTICS
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 45d961e994a1a..aeeba93819227 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -379,3 +379,9 @@ if(LLVM_WITH_Z3)
     ${Z3_INCLUDE_DIR}
     )
 endif()
+
+if(LLVM_INTEGRATE_LIBC)
+  set_property(TARGET LLVMSupport PROPERTY CXX_STANDARD 17)
+  target_include_directories(LLVMSupport PRIVATE "${LLVM_INCLUDE_DIR}/../../libc")
+  target_compile_options(LLVMSupport PRIVATE "-Wno-c99-extensions") # _Complex warnings.
+endif()
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp
index 8767208d20ec9..1e2aa2839fc8f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp
@@ -1540,7 +1540,7 @@ bool AMDGPULibCalls::evaluateScalarMathFunc(const FuncInfo &FInfo, double &Res0,
     return true;
 
   case AMDGPULibFunc::EI_EXP:
-    Res0 = exp(opr0);
+    Res0 = std::exp(opr0);
     return true;
 
   case AMDGPULibFunc::EI_EXP2:
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 7a5fd83cd9581..c56cd8898d17a 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -8356,4 +8356,23 @@ TEST(APFloatTest, hasSignBitInMSB) {
   EXPECT_FALSE(APFloat::hasSignBitInMSB(APFloat::Float8E8M0FNU()));
 }
 
+#ifdef LLVM_INTEGRATE_LIBC
+TEST(APFloatTest, expf) {
+  EXPECT_EQ(
+      1.0f,
+      llvm::exp(APFloat(0.0f), APFloat::rmNearestTiesToEven).convertToFloat());
+  EXPECT_EQ(
+      0x1.5bf0a8p1f,
+      llvm::exp(APFloat(1.0f), APFloat::rmNearestTiesToEven).convertToFloat());
+  EXPECT_EQ(
+      0x1.5bf0aap1f,
+      llvm::exp(APFloat(1.0f), APFloat::rmTowardPositive).convertToFloat());
+  EXPECT_EQ(
+      0x1.5bf0a8p1f,
+      llvm::exp(APFloat(1.0f), APFloat::rmTowardNegative).convertToFloat());
+  EXPECT_EQ(0x1.5bf0a8p1f,
+            llvm::exp(APFloat(1.0f), APFloat::rmTowardZero).convertToFloat());
+}
+#endif // LLVM_INTEGRATE_LIBC
+
 } // namespace

>From 32f6609a86ba8164407cd6099c7ab60cf7fe8438 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 13 Jun 2025 04:09:15 +0000
Subject: [PATCH 2/5] Fix typo and add more tests.

---
 llvm/CMakeLists.txt                |  2 +-
 llvm/unittests/ADT/APFloatTest.cpp | 53 ++++++++++++++++++++++++++++--
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 4128cceaf33fa..f1a1b39a60652 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -644,7 +644,7 @@ endif()
 
 set(LLVM_ENABLE_Z3_SOLVER_DEFAULT "${Z3_FOUND}")
 
-set(LLVM_INTEGRATE_LIBC "OFF" CACHE STRING "Use LLVM libc codes directly if available.")
+set(LLVM_INTEGRATE_LIBC "OFF" CACHE STRING "Use LLVM libc code directly if available.")
 
 if(LLVM_INTEGRATE_LIBC)
   message(STATUS "LLVM_INTEGRATE_LIBC is ${LLVM_INTEGRATE_LIBC}")
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index c56cd8898d17a..f7e5a64ba9306 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "gtest/gtest.h"
 #include <cmath>
+#include <limits>
 #include <ostream>
 #include <string>
 #include <tuple>
@@ -8358,9 +8359,24 @@ TEST(APFloatTest, hasSignBitInMSB) {
 
 #ifdef LLVM_INTEGRATE_LIBC
 TEST(APFloatTest, expf) {
-  EXPECT_EQ(
-      1.0f,
-      llvm::exp(APFloat(0.0f), APFloat::rmNearestTiesToEven).convertToFloat());
+  std::array<llvm::RoundingMode, 4> allRoundingModes = {
+      APFloat::rmNearestTiesToEven, APFloat::rmTowardPositive,
+      APFloat::rmTowardNegative, APFloat::rmTowardZero};
+  for (auto rm : allRoundingModes) {
+    // exp(+-0) = 1 for all rounding modes.
+    EXPECT_EQ(1.0f, llvm::exp(APFloat(0.0f), rm).convertToFloat());
+    EXPECT_EQ(1.0f, llvm::exp(APFloat(-0.0f), rm).convertToFloat());
+    // exp(+Inf) = +Inf for all rounding modes.
+    EXPECT_EQ(std::numeric_limits<float>::infinity(),
+              llvm::exp(APFloat::getInf(APFloat::IEEEsingle(), false), rm)
+                  .convertToFloat());
+    // exp(-Inf) = 0 for all rounding modes.
+    EXPECT_EQ(0.0f, llvm::exp(APFloat::getInf(APFloat::IEEEsingle(), true), rm)
+                        .convertToFloat());
+    // exp(NaN) = NaN for all rounding modes.
+    EXPECT_TRUE(llvm::exp(APFloat::getNaN(APFloat::IEEEsingle()), rm).isNaN());
+  }
+  // exp(1)
   EXPECT_EQ(
       0x1.5bf0a8p1f,
       llvm::exp(APFloat(1.0f), APFloat::rmNearestTiesToEven).convertToFloat());
@@ -8372,6 +8388,37 @@ TEST(APFloatTest, expf) {
       llvm::exp(APFloat(1.0f), APFloat::rmTowardNegative).convertToFloat());
   EXPECT_EQ(0x1.5bf0a8p1f,
             llvm::exp(APFloat(1.0f), APFloat::rmTowardZero).convertToFloat());
+  // exp(float max)
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            llvm::exp(APFloat::getLargest(APFloat::IEEEsingle(), false),
+                      APFloat::rmNearestTiesToEven)
+                .convertToFloat());
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            llvm::exp(APFloat::getLargest(APFloat::IEEEsingle(), false),
+                      APFloat::rmTowardPositive)
+                .convertToFloat());
+  EXPECT_EQ(std::numeric_limits<float>::max(),
+            llvm::exp(APFloat::getLargest(APFloat::IEEEsingle(), false),
+                      APFloat::rmTowardNegative)
+                .convertToFloat());
+  EXPECT_EQ(std::numeric_limits<float>::max(),
+            llvm::exp(APFloat::getLargest(APFloat::IEEEsingle(), false),
+                      APFloat::rmTowardZero)
+                .convertToFloat());
+  // exp(min_denormal)
+  EXPECT_EQ(1.0f, llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
+                            APFloat::rmNearestTiesToEven)
+                      .convertToFloat());
+  EXPECT_EQ(0x1.000002p0,
+            llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
+                      APFloat::rmTowardPositive)
+                .convertToFloat());
+  EXPECT_EQ(1.0f, llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
+                            APFloat::rmTowardNegative)
+                      .convertToFloat());
+  EXPECT_EQ(1.0f, llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
+                            APFloat::rmTowardZero)
+                      .convertToFloat());
 }
 #endif // LLVM_INTEGRATE_LIBC
 

>From d43491bf2f30923dd4b03d2fe8355947709c240a Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 13 Jun 2025 14:16:20 +0000
Subject: [PATCH 3/5] Add directional rounding version to LLVM libc and use
 that in APFloat.

---
 libc/src/__support/math/expf.h |  9 +++++++++
 llvm/lib/Support/APFloat.cpp   | 37 +++++++++++++++++-----------------
 2 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index 88c151492a041..d401993a75fc9 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -109,6 +109,15 @@ static constexpr float expf(float x) {
   return static_cast<float>(exp_hi * exp_mid * exp_lo);
 }
 
+// Directional rounding version of expf.
+LIBC_INLINE static float expf(float x, int rounding_mode) {
+  int current_rounding_mode = fputil::get_round();
+  fputil::set_round(rounding_mode);
+  float result = expf(x);
+  fputil::set_round(current_rounding_mode);
+  return result;
+}
+
 } // namespace math
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 150853743540d..574d0c233c425 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -5607,28 +5607,27 @@ float APFloat::convertToFloat() const {
 }
 
 #ifdef LLVM_INTEGRATE_LIBC
-APFloat exp(const APFloat &X, RoundingMode rounding_mode) {
+static constexpr int getFEnvRoundingMode(llvm::RoundingMode rm) {
+  switch (rm) {
+  case APFloat::rmTowardPositive:
+    return FE_UPWARD;
+  case APFloat::rmTowardNegative:
+    return FE_DOWNWARD;
+  case APFloat::rmTowardZero:
+    return FE_TOWARDZERO;
+  default:
+    // TODO: fix rmNearestTiesToAway for platform without FE_TONEARESTFROMZERO.
+    return FE_TONEAREST;
+  };
+}
+
+APFloat exp(const APFloat &X,
+            RoundingMode rounding_mode = APFloat::rmNearestTiesToEven) {
   assert((&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) &&
          "Float semantics is not IEEEsingle");
   if (&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) {
-    int current_rounding_mode = fegetround();
-    switch (rounding_mode) {
-    case APFloat::rmNearestTiesToEven:
-      fesetround(FE_TONEAREST);
-      break;
-    case APFloat::rmTowardPositive:
-      fesetround(FE_UPWARD);
-      break;
-    case APFloat::rmTowardNegative:
-      fesetround(FE_DOWNWARD);
-      break;
-    case APFloat::rmTowardZero:
-      fesetround(FE_TOWARDZERO);
-      break;
-    default:
-    }
-    float result = LIBC_NAMESPACE::shared::expf(X.convertToFloat());
-    fesetround(current_rounding_mode);
+    float result = LIBC_NAMESPACE::shared::expf(
+        X.convertToFloat(), getFEnvRoundingMode(rounding_mode));
     return APFloat(result);
   }
   llvm_unreachable("Unexpected semantics");

>From f134cb785f59348d6a668dedfe6e5ed6fa896c73 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 13 Jun 2025 14:21:45 +0000
Subject: [PATCH 4/5] Only change rounding modes if they are different.

---
 libc/src/__support/math/expf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index d401993a75fc9..6b0498428bd13 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -112,6 +112,9 @@ static constexpr float expf(float x) {
 // Directional rounding version of expf.
 LIBC_INLINE static float expf(float x, int rounding_mode) {
   int current_rounding_mode = fputil::get_round();
+  if (rounding_mode == current_rounding_mode)
+    return expf(x);
+
   fputil::set_round(rounding_mode);
   float result = expf(x);
   fputil::set_round(current_rounding_mode);

>From d18947d256236ddd4d1dd19a08d133c399bad9ee Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 13 Jun 2025 15:36:32 +0000
Subject: [PATCH 5/5] Omit declarations when LLVM_INTEGRATE_LIBC is off and fix
 default rounding mode declaration.

---
 llvm/include/llvm/ADT/APFloat.h    |  9 +++++++--
 llvm/lib/Support/APFloat.cpp       |  3 +--
 llvm/unittests/ADT/APFloatTest.cpp | 13 ++++++++++++-
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 6f6dd3c014584..731c972443f42 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1522,9 +1522,12 @@ class APFloat : public APFloatBase {
   friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
   friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
   friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
-  friend APFloat exp(const APFloat &X, roundingMode RM);
   friend IEEEFloat;
   friend DoubleAPFloat;
+
+#ifdef LLVM_INTEGRATE_LIBC
+  friend APFloat exp(const APFloat &X, roundingMode RM);
+#endif // LLVM_INTEGRATE_LIBC)
 };
 
 static_assert(sizeof(APFloat) == sizeof(detail::IEEEFloat),
@@ -1658,9 +1661,11 @@ inline APFloat maximumnum(const APFloat &A, const APFloat &B) {
   return A < B ? B : A;
 }
 
+#ifdef LLVM_INTEGRATE_LIBC
 /// Implement IEEE 754-2019 exp functions.
 LLVM_READONLY
-APFloat exp(const APFloat &X, RoundingMode RM);
+APFloat exp(const APFloat &X, RoundingMode RM = APFloat::rmNearestTiesToEven);
+#endif // LLVM_INTEGRATE_LIBC
 
 inline raw_ostream &operator<<(raw_ostream &OS, const APFloat &V) {
   V.print(OS);
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 574d0c233c425..d2948d37a5cf0 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -5621,8 +5621,7 @@ static constexpr int getFEnvRoundingMode(llvm::RoundingMode rm) {
   };
 }
 
-APFloat exp(const APFloat &X,
-            RoundingMode rounding_mode = APFloat::rmNearestTiesToEven) {
+APFloat exp(const APFloat &X, RoundingMode rounding_mode) {
   assert((&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) &&
          "Float semantics is not IEEEsingle");
   if (&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) {
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index f7e5a64ba9306..3eef9287b8abf 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -8409,7 +8409,7 @@ TEST(APFloatTest, expf) {
   EXPECT_EQ(1.0f, llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
                             APFloat::rmNearestTiesToEven)
                       .convertToFloat());
-  EXPECT_EQ(0x1.000002p0,
+  EXPECT_EQ(0x1.000002p0f,
             llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
                       APFloat::rmTowardPositive)
                 .convertToFloat());
@@ -8419,6 +8419,17 @@ TEST(APFloatTest, expf) {
   EXPECT_EQ(1.0f, llvm::exp(APFloat::getSmallest(APFloat::IEEEsingle(), false),
                             APFloat::rmTowardZero)
                       .convertToFloat());
+  // Default rounding mode.
+  // exp(-1)
+  EXPECT_EQ(0x1.78b564p-2f, llvm::exp(APFloat(-1.0f)).convertToFloat());
+  EXPECT_EQ(
+      0x1.78b564p-2f,
+      llvm::exp(APFloat(-1.0f), APFloat::rmTowardPositive).convertToFloat());
+  EXPECT_EQ(
+      0x1.78b562p-2f,
+      llvm::exp(APFloat(-1.0f), APFloat::rmTowardNegative).convertToFloat());
+  EXPECT_EQ(0x1.78b562p-2f,
+            llvm::exp(APFloat(-1.0f), APFloat::rmTowardZero).convertToFloat());
 }
 #endif // LLVM_INTEGRATE_LIBC
 



More information about the llvm-commits mailing list