From 4cc6905d7020140bf1facad3ad9c0888cb7e4734 Mon Sep 17 00:00:00 2001 From: Matt Devereau 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 e15a98dc5a6779..f1931c145f0fcf 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 512d1aadd53467..4329d2e9a0556c 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 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 f1931c145f0fcf..6068c556ca6160 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 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 0aae13e30f2ab4..7b092917a1bb8f 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 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 7b092917a1bb8f..eb5c3b1008a789 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 c24eae8da3797b..263aa089e10e5e 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 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 6068c556ca6160..eea11e6ec4e533 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 74476cb5440c61..474b8d20fde16f 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 4329d2e9a0556c..2ec6e909ea242c 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 47618bc3259512..2c46e43173ae24 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 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 eb5c3b1008a789..f7ba1a827b4af6 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 eea11e6ec4e533..45dc5cb8bc0f42 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 + 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 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 3208147101c0d7..08e8f69cee4d25 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 f7ba1a827b4af6..5e8c7c73a690d7 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 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 45dc5cb8bc0f42..618b320086ba59 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