[llvm] Enable logf128 constant folding for hosts with 128bit long double (PR #96287)

Matthew Devereau via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 6 07:52:42 PDT 2024


https://github.com/MDevereau updated https://github.com/llvm/llvm-project/pull/96287

>From 4cc6905d7020140bf1facad3ad9c0888cb7e4734 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Fri, 21 Jun 2024 08:34:04 +0000
Subject: [PATCH 1/7] Enable logf128 constant folding for AArch64

AArch64 has a long double bit length of 128. Therefore, it can benefit
from constant fp128 folding. GCC versions more recent than version 12
must use the _Float128 type for logf128.
---
 llvm/include/llvm/Support/float128.h  | 9 ++++++++-
 llvm/lib/Analysis/ConstantFolding.cpp | 4 ++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h
index e15a98dc5a677..f1931c145f0fc 100644
--- a/llvm/include/llvm/Support/float128.h
+++ b/llvm/include/llvm/Support/float128.h
@@ -11,7 +11,14 @@
 
 namespace llvm {
 
-#if defined(__clang__) && defined(__FLOAT128__) &&                             \
+#if defined(__aarch64__)
+#define HAS_IEE754_FLOAT128
+#if (defined(__GNUC__) && __GNUC__ > 12)
+typedef _Float128 float128;
+#else
+typedef long double float128;
+#endif
+#elif defined(__clang__) && defined(__FLOAT128__) &&                           \
     defined(__SIZEOF_INT128__) && !defined(__LONG_DOUBLE_IBM128__)
 #define HAS_IEE754_FLOAT128
 typedef __float128 float128;
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 512d1aadd5346..4329d2e9a0556 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1784,8 +1784,8 @@ Constant *ConstantFoldFP(double (*NativeFP)(double), const APFloat &V,
 }
 
 #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128)
-Constant *ConstantFoldFP128(long double (*NativeFP)(long double),
-                            const APFloat &V, Type *Ty) {
+Constant *ConstantFoldFP128(float128 (*NativeFP)(float128), const APFloat &V,
+                            Type *Ty) {
   llvm_fenv_clearexcept();
   float128 Result = NativeFP(V.convertToQuad());
   if (llvm_fenv_testexcept()) {

>From 97a0b2005dc477c491b942933f5ecae7acf187e8 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Wed, 26 Jun 2024 13:57:59 +0000
Subject: [PATCH 2/7] Remove aarch64 constraint

Also enable optimisation without cmake opt-in
---
 llvm/include/llvm/Support/float128.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h
index f1931c145f0fc..6068c556ca616 100644
--- a/llvm/include/llvm/Support/float128.h
+++ b/llvm/include/llvm/Support/float128.h
@@ -11,7 +11,8 @@
 
 namespace llvm {
 
-#if defined(__aarch64__)
+#if !defined(__LONG_DOUBLE_IBM128__) && (__SIZEOF_LONG_DOUBLE__ == 16) &&      \
+    (__SIZEOF_INT128__ == 16) && (__LDBL_MANT_DIG__ == 113)
 #define HAS_IEE754_FLOAT128
 #if (defined(__GNUC__) && __GNUC__ > 12)
 typedef _Float128 float128;

>From 94c6914a6048c8f044bbe573539f81d7fd9dfecf Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Wed, 26 Jun 2024 15:08:10 +0000
Subject: [PATCH 3/7] Enable optimization without opt-in

---
 llvm/cmake/config-ix.cmake | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index 0aae13e30f2ab..7b092917a1bb8 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -247,17 +247,6 @@ else()
   set(HAVE_LIBEDIT 0)
 endif()
 
-if(LLVM_HAS_LOGF128)
-  include(CheckCXXSymbolExists)
-  check_cxx_symbol_exists(logf128 math.h HAS_LOGF128)
-
-  if(LLVM_HAS_LOGF128 STREQUAL FORCE_ON AND NOT HAS_LOGF128)
-    message(FATAL_ERROR "Failed to configure logf128")
-  endif()
-
-  set(LLVM_HAS_LOGF128 "${HAS_LOGF128}")
-endif()
-
 # function checks
 check_symbol_exists(arc4random "stdlib.h" HAVE_DECL_ARC4RANDOM)
 find_package(Backtrace)
@@ -271,6 +260,8 @@ if(C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW)
   set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unguarded-availability-new")
 endif()
 
+check_function_exists(logf128 math.h HAS_LOGF128)
+
 # Determine whether we can register EH tables.
 check_symbol_exists(__register_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_REGISTER_FRAME)
 check_symbol_exists(__deregister_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_DEREGISTER_FRAME)

>From 422fed86405852d798d93c59a64d449bc659b056 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Thu, 11 Jul 2024 14:30:01 +0000
Subject: [PATCH 4/7] Check for viable logf128 and use that for float128's
 typedef

---
 llvm/cmake/config-ix.cmake            | 58 ++++++++++++++++++++++++++-
 llvm/include/llvm/ADT/APFloat.h       |  4 +-
 llvm/include/llvm/Support/float128.h  | 21 ++++------
 llvm/lib/Analysis/CMakeLists.txt      |  6 ---
 llvm/lib/Analysis/ConstantFolding.cpp |  4 +-
 llvm/lib/Support/APFloat.cpp          |  4 +-
 6 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index 7b092917a1bb8..eb5c3b1008a78 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -260,7 +260,63 @@ if(C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW)
   set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unguarded-availability-new")
 endif()
 
-check_function_exists(logf128 math.h HAS_LOGF128)
+function(logf128_test testname definition)
+  unset(LOGF128_TEST_RUN CACHE)
+  unset(LOGF128_TEST_COMPILE CACHE)
+  try_run(
+    LOGF128_TEST_RUN
+    LOGF128_TEST_COMPILE
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}/logf128_${testname}.cpp
+    LINK_LIBRARIES m
+  )
+  if(LOGF128_TEST_RUN)
+    set (LLVM_HAS_LOGF128 true CACHE INTERNAL "")
+    set(${definition} true CACHE INTERNAL "")
+    message(STATUS "LLVM: found logf128 with type ${testname}")
+    add_compile_definitions(${definition})
+  endif()
+endfunction()
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/logf128_long_double.cpp"
+"
+extern \"C\" {
+long double logf128(long double);
+}
+int main() {
+  long double value = logf128(32.0);
+  if (value > 3.465730L & value < 3.465740L)
+    return 1;
+  return 0;
+}")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/logf128___float128.cpp"
+"
+extern \"C\" {
+__float128 logf128(__float128);
+}
+int main() {
+  __float128 value = logf128(32.0);
+  if (value > 3.465730L & value < 3.465740L)
+    return 1;
+  return 0;
+}")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/logf128__Float128.cpp"
+"
+extern \"C\" {
+_Float128 logf128(_Float128);
+}
+int main() {
+  _Float128 value = logf128(32.0);
+  if (value > 3.465730L & value < 3.465740L)
+    return 1;
+  return 0;
+}")
+
+logf128_test("long_double" HAS_LONG_DOUBLE_LOGF128)
+logf128_test("__float128" HAS__FLOAT128_LOGF128)
+logf128_test("_Float128" HAS_FLOAT128_LOGF128)
 
 # Determine whether we can register EH tables.
 check_symbol_exists(__register_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_REGISTER_FRAME)
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index c24eae8da3797..263aa089e10e5 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -370,7 +370,7 @@ class IEEEFloat final : public APFloatBase {
   Expected<opStatus> convertFromString(StringRef, roundingMode);
   APInt bitcastToAPInt() const;
   double convertToDouble() const;
-#ifdef HAS_IEE754_FLOAT128
+#if defined(HAS_IEE754_FLOAT128)
   float128 convertToQuad() const;
 #endif
   float convertToFloat() const;
@@ -1267,7 +1267,7 @@ class APFloat : public APFloatBase {
   /// \pre The APFloat must be built using semantics, that can be represented by
   /// the host float type without loss of precision. It can be IEEEquad and
   /// shorter semantics, like IEEEdouble and others.
-#ifdef HAS_IEE754_FLOAT128
+#if defined(HAS_IEE754_FLOAT128)
   float128 convertToQuad() const;
 #endif
 
diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h
index 6068c556ca616..eea11e6ec4e53 100644
--- a/llvm/include/llvm/Support/float128.h
+++ b/llvm/include/llvm/Support/float128.h
@@ -11,23 +11,18 @@
 
 namespace llvm {
 
-#if !defined(__LONG_DOUBLE_IBM128__) && (__SIZEOF_LONG_DOUBLE__ == 16) &&      \
-    (__SIZEOF_INT128__ == 16) && (__LDBL_MANT_DIG__ == 113)
-#define HAS_IEE754_FLOAT128
-#if (defined(__GNUC__) && __GNUC__ > 12)
+#ifdef HAS_FLOAT128_LOGF128
 typedef _Float128 float128;
-#else
-typedef long double float128;
-#endif
-#elif defined(__clang__) && defined(__FLOAT128__) &&                           \
-    defined(__SIZEOF_INT128__) && !defined(__LONG_DOUBLE_IBM128__)
 #define HAS_IEE754_FLOAT128
+#elif HAS__FLOAT128_LOGF128
 typedef __float128 float128;
-#elif defined(__FLOAT128__) && defined(__SIZEOF_INT128__) &&                   \
-    !defined(__LONG_DOUBLE_IBM128__) &&                                        \
-    (defined(__GNUC__) || defined(__GNUG__))
+extern "C" {
+float128 logf128(float128);
+}
+#define HAS_IEE754_FLOAT128
+#elif HAS_LONG_DOUBLE_LOGF128
+typedef long double float128;
 #define HAS_IEE754_FLOAT128
-typedef _Float128 float128;
 #endif
 
 } // namespace llvm
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 74476cb5440c6..474b8d20fde16 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -159,9 +159,3 @@ add_llvm_component_library(LLVMAnalysis
   Support
   TargetParser
   )
-
-include(CheckCXXSymbolExists)
-check_cxx_symbol_exists(logf128 math.h HAS_LOGF128)
-if(HAS_LOGF128)
- target_compile_definitions(LLVMAnalysis PRIVATE HAS_LOGF128)
-endif()
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 4329d2e9a0556..2ec6e909ea242 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1783,7 +1783,7 @@ Constant *ConstantFoldFP(double (*NativeFP)(double), const APFloat &V,
   return GetConstantFoldFPValue(Result, Ty);
 }
 
-#if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128)
+#if defined(HAS_IEE754_FLOAT128)
 Constant *ConstantFoldFP128(float128 (*NativeFP)(float128), const APFloat &V,
                             Type *Ty) {
   llvm_fenv_clearexcept();
@@ -2116,7 +2116,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
     if (IntrinsicID == Intrinsic::canonicalize)
       return constantFoldCanonicalize(Ty, Call, U);
 
-#if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128)
+#if defined(HAS_IEE754_FLOAT128)
     if (Ty->isFP128Ty()) {
       if (IntrinsicID == Intrinsic::log) {
         float128 Result = logf128(Op->getValueAPF().convertToQuad());
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 47618bc325951..2c46e43173ae2 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -3721,7 +3721,7 @@ double IEEEFloat::convertToDouble() const {
   return api.bitsToDouble();
 }
 
-#ifdef HAS_IEE754_FLOAT128
+#if defined(HAS_IEE754_FLOAT128)
 float128 IEEEFloat::convertToQuad() const {
   assert(semantics == (const llvm::fltSemantics *)&semIEEEquad &&
          "Float semantics are not IEEEquads");
@@ -5351,7 +5351,7 @@ double APFloat::convertToDouble() const {
   return Temp.getIEEE().convertToDouble();
 }
 
-#ifdef HAS_IEE754_FLOAT128
+#if defined(HAS_IEE754_FLOAT128)
 float128 APFloat::convertToQuad() const {
   if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEquad)
     return getIEEE().convertToQuad();

>From 613f6a4b316753bcc885ec5a7f3628497a474b12 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Wed, 17 Jul 2024 13:52:42 +0000
Subject: [PATCH 5/7] Remove cmake tests

---
 llvm/cmake/config-ix.cmake           | 61 ++--------------------------
 llvm/include/llvm/Support/float128.h | 18 ++++----
 2 files changed, 11 insertions(+), 68 deletions(-)

diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index eb5c3b1008a78..f7ba1a827b4af 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -260,63 +260,10 @@ if(C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW)
   set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unguarded-availability-new")
 endif()
 
-function(logf128_test testname definition)
-  unset(LOGF128_TEST_RUN CACHE)
-  unset(LOGF128_TEST_COMPILE CACHE)
-  try_run(
-    LOGF128_TEST_RUN
-    LOGF128_TEST_COMPILE
-    ${CMAKE_CURRENT_BINARY_DIR}
-    ${CMAKE_CURRENT_BINARY_DIR}/logf128_${testname}.cpp
-    LINK_LIBRARIES m
-  )
-  if(LOGF128_TEST_RUN)
-    set (LLVM_HAS_LOGF128 true CACHE INTERNAL "")
-    set(${definition} true CACHE INTERNAL "")
-    message(STATUS "LLVM: found logf128 with type ${testname}")
-    add_compile_definitions(${definition})
-  endif()
-endfunction()
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/logf128_long_double.cpp"
-"
-extern \"C\" {
-long double logf128(long double);
-}
-int main() {
-  long double value = logf128(32.0);
-  if (value > 3.465730L & value < 3.465740L)
-    return 1;
-  return 0;
-}")
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/logf128___float128.cpp"
-"
-extern \"C\" {
-__float128 logf128(__float128);
-}
-int main() {
-  __float128 value = logf128(32.0);
-  if (value > 3.465730L & value < 3.465740L)
-    return 1;
-  return 0;
-}")
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/logf128__Float128.cpp"
-"
-extern \"C\" {
-_Float128 logf128(_Float128);
-}
-int main() {
-  _Float128 value = logf128(32.0);
-  if (value > 3.465730L & value < 3.465740L)
-    return 1;
-  return 0;
-}")
-
-logf128_test("long_double" HAS_LONG_DOUBLE_LOGF128)
-logf128_test("__float128" HAS__FLOAT128_LOGF128)
-logf128_test("_Float128" HAS_FLOAT128_LOGF128)
+check_cxx_symbol_exists(logf128 cmath HAS_LOGF128)
+if(HAS_LOGF128)
+    add_compile_definitions(HAS_LOGF128)
+endif()
 
 # Determine whether we can register EH tables.
 check_symbol_exists(__register_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_REGISTER_FRAME)
diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h
index eea11e6ec4e53..45dc5cb8bc0f4 100644
--- a/llvm/include/llvm/Support/float128.h
+++ b/llvm/include/llvm/Support/float128.h
@@ -9,21 +9,17 @@
 #ifndef LLVM_FLOAT128
 #define LLVM_FLOAT128
 
+#include <cmath>
+
 namespace llvm {
 
-#ifdef HAS_FLOAT128_LOGF128
-typedef _Float128 float128;
-#define HAS_IEE754_FLOAT128
-#elif HAS__FLOAT128_LOGF128
-typedef __float128 float128;
-extern "C" {
-float128 logf128(float128);
-}
-#define HAS_IEE754_FLOAT128
-#elif HAS_LONG_DOUBLE_LOGF128
-typedef long double float128;
+#ifdef HAS_LOGF128
+#if (__LDBL_MANT_DIG__ == 113) && !defined(__LONG_DOUBLE_IBM128__) &&          \
+    (__SIZEOF_INT128__ == 16)
+typedef decltype(logf128(0.)) float128;
 #define HAS_IEE754_FLOAT128
 #endif
+#endif // HAS_LOGF128
 
 } // namespace llvm
 #endif // LLVM_FLOAT128

>From 57053167e044b509d4765d0caa00f64083588b90 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Thu, 18 Jul 2024 10:32:51 +0000
Subject: [PATCH 6/7] Lit uses LLVM_HAS_LOGF128 to run tests and is no longer a
 command line option

---
 llvm/CMakeLists.txt        | 2 --
 llvm/cmake/config-ix.cmake | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 3208147101c0d..08e8f69cee4d2 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -560,8 +560,6 @@ set(LLVM_USE_STATIC_ZSTD FALSE CACHE BOOL "Use static version of zstd. Can be TR
 
 set(LLVM_ENABLE_CURL "OFF" CACHE STRING "Use libcurl for the HTTP client if available. Can be ON, OFF, or FORCE_ON")
 
-set(LLVM_HAS_LOGF128 "OFF" CACHE STRING "Use logf128 to constant fold fp128 logarithm calls. Can be ON, OFF, or FORCE_ON")
-
 set(LLVM_ENABLE_HTTPLIB "OFF" CACHE STRING "Use cpp-httplib HTTP server library if available. Can be ON, OFF, or FORCE_ON")
 
 set(LLVM_Z3_INSTALL_DIR "" CACHE STRING "Install directory of the Z3 solver.")
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index f7ba1a827b4af..5e8c7c73a690d 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -262,6 +262,7 @@ endif()
 
 check_cxx_symbol_exists(logf128 cmath HAS_LOGF128)
 if(HAS_LOGF128)
+    set(LLVM_HAS_LOGF128 On)
     add_compile_definitions(HAS_LOGF128)
 endif()
 

>From 6ceda722a73b47761023837f0e0bbc3495ef5e1d Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Tue, 6 Aug 2024 14:51:06 +0000
Subject: [PATCH 7/7] Remove check for __LDBL_MANT_DIG__

---
 llvm/include/llvm/Support/float128.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h
index 45dc5cb8bc0f4..618b320086ba5 100644
--- a/llvm/include/llvm/Support/float128.h
+++ b/llvm/include/llvm/Support/float128.h
@@ -14,8 +14,7 @@
 namespace llvm {
 
 #ifdef HAS_LOGF128
-#if (__LDBL_MANT_DIG__ == 113) && !defined(__LONG_DOUBLE_IBM128__) &&          \
-    (__SIZEOF_INT128__ == 16)
+#if !defined(__LONG_DOUBLE_IBM128__) && (__SIZEOF_INT128__ == 16)
 typedef decltype(logf128(0.)) float128;
 #define HAS_IEE754_FLOAT128
 #endif



More information about the llvm-commits mailing list