diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index d681b1ccab6299..b03d89a43c34b0 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 f76eacb9d51366..471dd1615c2e7b 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -246,17 +246,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) @@ -270,6 +259,13 @@ if(C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unguarded-availability-new") endif() +check_cxx_symbol_exists(logf128 cmath HAS_LOGF128) +check_symbol_exists(__powerpc64le__ "" __PPC64LE) +if(HAS_LOGF128 AND NOT __PPC64LE) + set(LLVM_HAS_LOGF128 On) + 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) check_symbol_exists(__deregister_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_DEREGISTER_FRAME) diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index 7039e961bff82d..925d03d4c06670 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -19,7 +19,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/float128.h" #include #define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \ @@ -378,9 +377,6 @@ class IEEEFloat final : public APFloatBase { Expected convertFromString(StringRef, roundingMode); APInt bitcastToAPInt() const; double convertToDouble() const; -#ifdef HAS_IEE754_FLOAT128 - float128 convertToQuad() const; -#endif float convertToFloat() const; /// @} @@ -1274,14 +1270,9 @@ class APFloat : public APFloatBase { /// shorter semantics, like IEEEsingle and others. double convertToDouble() const; - /// Converts this APFloat to host float value. - /// - /// \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 - float128 convertToQuad() const; -#endif + /// Return true if this APFloat has quadruple precision floating point + /// semantics + bool isValidIEEEQuad() const; /// Converts this APFloat to host float value. /// diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 65ba3f15305c78..13837413ae49fe 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -17,7 +17,6 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/float128.h" #include #include #include @@ -1677,13 +1676,6 @@ class [[nodiscard]] APInt { /// any bit width. Exactly 64 bits will be translated. double bitsToDouble() const { return llvm::bit_cast(getWord(0)); } -#ifdef HAS_IEE754_FLOAT128 - float128 bitsToQuad() const { - __uint128_t ul = ((__uint128_t)U.pVal[1] << 64) + U.pVal[0]; - return llvm::bit_cast(ul); - } -#endif - /// Converts APInt bits to a float /// /// The conversion does not do a translation from integer to float, it just diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h index e15a98dc5a6779..618b320086ba59 100644 --- a/llvm/include/llvm/Support/float128.h +++ b/llvm/include/llvm/Support/float128.h @@ -9,18 +9,16 @@ #ifndef LLVM_FLOAT128 #define LLVM_FLOAT128 +#include + namespace llvm { -#if defined(__clang__) && defined(__FLOAT128__) && \ - defined(__SIZEOF_INT128__) && !defined(__LONG_DOUBLE_IBM128__) -#define HAS_IEE754_FLOAT128 -typedef __float128 float128; -#elif defined(__FLOAT128__) && defined(__SIZEOF_INT128__) && \ - !defined(__LONG_DOUBLE_IBM128__) && \ - (defined(__GNUC__) || defined(__GNUG__)) +#ifdef HAS_LOGF128 +#if !defined(__LONG_DOUBLE_IBM128__) && (__SIZEOF_INT128__ == 16) +typedef decltype(logf128(0.)) float128; #define HAS_IEE754_FLOAT128 -typedef _Float128 float128; #endif +#endif // HAS_LOGF128 } // namespace llvm #endif // LLVM_FLOAT128 diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 393803fad89383..3127f45cc54cb1 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -162,9 +162,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 defcacdfa8b105..81c4d4ec5be412 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -54,6 +54,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/float128.h" #include #include #include @@ -1741,7 +1742,7 @@ Constant *GetConstantFoldFPValue(double V, Type *Ty) { llvm_unreachable("Can only constant fold half/float/double"); } -#if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) +#if defined(HAS_IEE754_FLOAT128) Constant *GetConstantFoldFPValue128(float128 V, Type *Ty) { if (Ty->isFP128Ty()) return ConstantFP::get(Ty, V); @@ -1781,11 +1782,25 @@ 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) +float128 ConvertToQuad(const APFloat &Apf) { + APInt Api = Apf.bitcastToAPInt(); + __uint128_t Uint128 = + ((__uint128_t)Api.extractBitsAsZExtValue(64, 64) << 64) + + Api.extractBitsAsZExtValue(64, 0); + return llvm::bit_cast(Uint128); +} +#endif + +#if defined(HAS_IEE754_FLOAT128) Constant *ConstantFoldFP128(float128 (*NativeFP)(float128), const APFloat &V, Type *Ty) { llvm_fenv_clearexcept(); - float128 Result = NativeFP(V.convertToQuad()); + if (!V.isValidIEEEQuad()) + return nullptr; + + float128 Result = NativeFP(ConvertToQuad(V)); + if (llvm_fenv_testexcept()) { llvm_fenv_clearexcept(); return nullptr; @@ -2114,13 +2129,16 @@ 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()); + APFloat Value = Op->getValueAPF(); + if (!Value.isValidIEEEQuad()) + return nullptr; + + float128 Result = logf128(ConvertToQuad(Value)); return GetConstantFoldFPValue128(Result, Ty); } - LibFunc Fp128Func = NotLibFunc; if (TLI->getLibFunc(Name, Fp128Func) && TLI->has(Fp128Func) && Fp128Func == LibFunc_logl) diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 7f68c5ab9b7cf7..2ddf99f56f88d5 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -3749,15 +3749,6 @@ double IEEEFloat::convertToDouble() const { return api.bitsToDouble(); } -#ifdef HAS_IEE754_FLOAT128 -float128 IEEEFloat::convertToQuad() const { - assert(semantics == (const llvm::fltSemantics *)&semIEEEquad && - "Float semantics are not IEEEquads"); - APInt api = bitcastToAPInt(); - return api.bitsToQuad(); -} -#endif - /// Integer bit is explicit in this format. Intel hardware (387 and later) /// does not support these bit patterns: /// exponent = all 1's, integer bit 0, significand 0 ("pseudoinfinity") @@ -5406,20 +5397,9 @@ double APFloat::convertToDouble() const { return Temp.getIEEE().convertToDouble(); } -#ifdef HAS_IEE754_FLOAT128 -float128 APFloat::convertToQuad() const { - if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEquad) - return getIEEE().convertToQuad(); - assert(getSemantics().isRepresentableBy(semIEEEquad) && - "Float semantics is not representable by IEEEquad"); - APFloat Temp = *this; - bool LosesInfo; - opStatus St = Temp.convert(semIEEEquad, rmNearestTiesToEven, &LosesInfo); - assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision"); - (void)St; - return Temp.getIEEE().convertToQuad(); +bool APFloat::isValidIEEEQuad() const { + return (&getSemantics() == (const llvm::fltSemantics *)&semIEEEquad); } -#endif float APFloat::convertToFloat() const { if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle)