From 04772430a7be186a671f8a7c4ecfe30b5c930907 Mon Sep 17 00:00:00 2001 From: Matthew Devereau Date: Wed, 29 May 2024 06:13:02 +0100 Subject: [PATCH 1/3] Constant Fold logf128 calls (#90611) This is a second attempt to land #84501 which failed on several targets. This patch adds the HAS_IEE754_FLOAT128 define which makes the check for typedef'ing float128 more precise by checking whether __uint128_t is available and checking if the host does not use __ibm128 which is prevalent on power pc targets and replaces IEEE754 float128s. --- llvm/CMakeLists.txt | 2 + llvm/cmake/config-ix.cmake | 11 ++ llvm/include/llvm/ADT/APFloat.h | 13 ++ llvm/include/llvm/ADT/APInt.h | 8 ++ llvm/include/llvm/Config/llvm-config.h.cmake | 3 + llvm/include/llvm/Support/float128.h | 26 ++++ llvm/lib/Analysis/CMakeLists.txt | 6 + llvm/lib/Analysis/ConstantFolding.cpp | 11 ++ llvm/lib/Support/APFloat.cpp | 24 ++++ llvm/test/CMakeLists.txt | 3 + .../InstSimplify/ConstProp/logf128.ll | 126 ++++++++++++++++++ llvm/test/lit.cfg.py | 3 + llvm/test/lit.site.cfg.py.in | 4 + 13 files changed, 240 insertions(+) create mode 100644 llvm/include/llvm/Support/float128.h create mode 100644 llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 3b69d027e006..687a9a689211 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -522,6 +522,8 @@ 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 5d430f974bbf..8b377a5d5942 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -263,6 +263,17 @@ if(LLVM_HAVE_LIBXAR) endif() 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) diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index 64caa5a76545..ebbb67b9e091 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -19,6 +19,7 @@ #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) \ @@ -354,6 +355,9 @@ public: Expected convertFromString(StringRef, roundingMode); APInt bitcastToAPInt() const; double convertToDouble() const; +#ifdef HAS_IEE754_FLOAT128 + float128 convertToQuad() const; +#endif float convertToFloat() const; /// @} @@ -1199,6 +1203,15 @@ public: /// 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 + /// Converts this APFloat to host float value. /// /// \pre The APFloat must be built using semantics, that can be represented by diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 6f2f25548cc8..330cfc8c709f 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -17,6 +17,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/float128.h" #include #include #include @@ -1663,6 +1664,13 @@ public: /// 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/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake index 012ae2174cc2..2f1dc9ec0f98 100644 --- a/llvm/include/llvm/Config/llvm-config.h.cmake +++ b/llvm/include/llvm/Config/llvm-config.h.cmake @@ -126,4 +126,7 @@ /* Define if plugins enabled */ #cmakedefine LLVM_ENABLE_PLUGINS +/* Define if logf128 is available */ +#cmakedefine LLVM_HAS_LOGF128 + #endif diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h new file mode 100644 index 000000000000..e15a98dc5a67 --- /dev/null +++ b/llvm/include/llvm/Support/float128.h @@ -0,0 +1,26 @@ +//===-- llvm/Support/float128.h - Compiler abstraction support --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FLOAT128 +#define LLVM_FLOAT128 + +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__)) +#define HAS_IEE754_FLOAT128 +typedef _Float128 float128; +#endif + +} // namespace llvm +#endif // LLVM_FLOAT128 diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index a694eee1ade0..b35764c7fb4b 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -195,3 +195,9 @@ 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 38cccb3ea3c2..0724b332608c 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2100,6 +2100,17 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, if (IntrinsicID == Intrinsic::canonicalize) return constantFoldCanonicalize(Ty, Call, U); +#if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) + if (Ty->isFP128Ty()) { + switch (IntrinsicID) { + default: + return nullptr; + case Intrinsic::log: + return ConstantFP::get(Ty, logf128(Op->getValueAPF().convertToQuad())); + } + } +#endif + if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) return nullptr; diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 4a73739b5282..815e9faccbbe 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -3670,6 +3670,15 @@ 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") @@ -5226,6 +5235,21 @@ 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(); +} +#endif + float APFloat::convertToFloat() const { if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) return getIEEE().convertToFloat(); diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt index 8cd77b72c987..6a7f3ff9a8be 100644 --- a/llvm/test/CMakeLists.txt +++ b/llvm/test/CMakeLists.txt @@ -25,6 +25,9 @@ llvm_canonicalize_cmake_booleans( LLVM_ENABLE_REVERSE_ITERATION LLVM_INCLUDE_DXIL_TESTS LLVM_TOOL_LLVM_DRIVER_BUILD + LLVM_INCLUDE_SPIRV_TOOLS_TESTS + LLVM_APPEND_VC_REV + LLVM_HAS_LOGF128 ) configure_lit_site_cfg( diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll b/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll new file mode 100644 index 000000000000..da56997f6938 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll @@ -0,0 +1,126 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instsimplify -S | FileCheck %s + +; REQUIRES: has_logf128 +declare fp128 @llvm.log.f128(fp128) + +define fp128 @log_e_64(){ +; CHECK-LABEL: define fp128 @log_e_64() { +; CHECK-NEXT: ret fp128 0xL300000000000000040010A2B23F3BAB7 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000004005000000000000) + ret fp128 %A +} + +define fp128 @log_e_smallest_positive_subnormal_number(){ +; CHECK-LABEL: define fp128 @log_e_smallest_positive_subnormal_number() { +; CHECK-NEXT: ret fp128 0xL3000000000000000C00C654628220780 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000010000000000000000) + ret fp128 %A +} + +define fp128 @log_e_largest_subnormal_number(){ +; CHECK-LABEL: define fp128 @log_e_largest_subnormal_number() { +; CHECK-NEXT: ret fp128 0xLD000000000000000C00C62D918CE2421 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xLFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF) + ret fp128 %A +} + +define fp128 @log_e_smallest_positive_normal_number(){ +; +; CHECK-LABEL: define fp128 @log_e_smallest_positive_normal_number() { +; CHECK-NEXT: ret fp128 0xLD000000000000000C00C62D918CE2421 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000000001000000000000) + ret fp128 %A +} + +define fp128 @log_e_largest_normal_number(){ +; CHECK-LABEL: define fp128 @log_e_largest_normal_number() { +; CHECK-NEXT: ret fp128 0xLF000000000000000400C62E42FEFA39E +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF) + ret fp128 %A +} + +define fp128 @log_e_largest_number_less_than_one(){ +; CHECK-LABEL: define fp128 @log_e_largest_number_less_than_one() { +; CHECK-NEXT: ret fp128 0xL0000000000000000BF8E000000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xLFFFFFFFFFFFFFFFF3FFEFFFFFFFFFFFF) + ret fp128 %A +} + +define fp128 @log_e_1(){ +; CHECK-LABEL: define fp128 @log_e_1() { +; CHECK-NEXT: ret fp128 0xL00000000000000000000000000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000003FFF000000000000) + ret fp128 %A +} + +define fp128 @log_e_smallest_number_larger_than_one(){ +; CHECK-LABEL: define fp128 @log_e_smallest_number_larger_than_one() { +; CHECK-NEXT: ret fp128 0xL00000000000000003F8F000000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000013FFF000000000000) + ret fp128 %A +} + +define fp128 @log_e_negative_2(){ +; CHECK-LABEL: define fp128 @log_e_negative_2() { +; CHECK-NEXT: ret fp128 0xL00000000000000007FFF800000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL0000000000000000C000000000000000) + ret fp128 %A +} + +define fp128 @log_e_0(){ +; CHECK-LABEL: define fp128 @log_e_0() { +; CHECK-NEXT: ret fp128 0xL0000000000000000FFFF000000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000000000000000000000) + ret fp128 %A +} + +define fp128 @log_e_negative_0(){ +; CHECK-LABEL: define fp128 @log_e_negative_0() { +; CHECK-NEXT: ret fp128 0xL0000000000000000FFFF000000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000008000000000000000) + ret fp128 %A +} + +define fp128 @log_e_infinity(){ +; CHECK-LABEL: define fp128 @log_e_infinity() { +; CHECK-NEXT: ret fp128 0xL00000000000000007FFF000000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000007FFF000000000000) + ret fp128 %A +} + +define fp128 @log_e_negative_infinity(){ +; CHECK-LABEL: define fp128 @log_e_negative_infinity() { +; CHECK-NEXT: ret fp128 0xL00000000000000007FFF800000000000 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL0000000000000000FFFF000000000000) + ret fp128 %A +} + +define fp128 @log_e_nan(){ +; CHECK-LABEL: define fp128 @log_e_nan() { +; CHECK-NEXT: ret fp128 0xL00000000000000007FFF800000000001 +; + %A = call fp128 @llvm.log.f128(fp128 noundef 0xL00000000000000007FFF000000000001) + ret fp128 %A +} + +define <2 x fp128> @log_e_negative_2_vector(){ +; CHECK-LABEL: define <2 x fp128> @log_e_negative_2_vector() { +; CHECK-NEXT: ret <2 x fp128> +; + %A = call <2 x fp128> @llvm.log.v2f128(<2 x fp128> ) + ret <2 x fp128> %A +} diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index 9cc8520960c2..36555fa40963 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -648,3 +648,6 @@ if "system-aix" in config.available_features: if config.use_classic_flang: config.available_features.add("classic_flang") + +if config.has_logf128: + config.available_features.add("has_logf128") diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index 20c1ecca1d43..cecf7d8c7b35 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -64,6 +64,10 @@ config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@ config.use_classic_flang = @LLVM_ENABLE_CLASSIC_FLANG@ config.enable_enable_autotuner = @LLVM_ENABLE_AUTOTUNER@ config.enable_build_for_common = @LLVM_BUILD_FOR_COMMON@ +config.spirv_tools_tests = @LLVM_INCLUDE_SPIRV_TOOLS_TESTS@ +config.have_vc_rev = @LLVM_APPEND_VC_REV@ +config.force_vc_rev = "@LLVM_FORCE_VC_REVISION@" +config.has_logf128 = @LLVM_HAS_LOGF128@ import lit.llvm lit.llvm.initialize(lit_config, config) -- Gitee From c59281f4466c6274473c5f17e982a6eafbf74b96 Mon Sep 17 00:00:00 2001 From: Matthew Devereau Date: Tue, 18 Jun 2024 13:27:25 +0100 Subject: [PATCH 2/3] ConstantFold logl calls (#94944) This is a follow up patch from #90611 which folds logl calls in the same manner as log.f128 calls. logl suffers from the same problem as logf128 of having slow calls to fp128 log functions which can be constant folded. However, logl is emitted with -fmath-errno and log.f128 is emitted by -fno-math-errno by certain intrinsics. --- llvm/lib/Analysis/ConstantFolding.cpp | 43 +++++++++++++---- .../InstSimplify/ConstProp/logf128.ll | 47 +++++++++++++++++++ 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 0724b332608c..47c910b89dbd 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1684,9 +1684,9 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { Name == "floor" || Name == "floorf" || Name == "fmod" || Name == "fmodf"; case 'l': - return Name == "log" || Name == "logf" || - Name == "log2" || Name == "log2f" || - Name == "log10" || Name == "log10f"; + return Name == "log" || Name == "logf" || Name == "log2" || + Name == "log2f" || Name == "log10" || Name == "log10f" || + Name == "logl"; case 'n': return Name == "nearbyint" || Name == "nearbyintf"; case 'p': @@ -1749,6 +1749,14 @@ Constant *GetConstantFoldFPValue(double V, Type *Ty) { llvm_unreachable("Can only constant fold half/float/double"); } +#if defined(HAS_IEE754_FLOAT128) +Constant *GetConstantFoldFPValue128(__float128 V, Type *Ty) { + if (Ty->isFP128Ty()) + return ConstantFP::get(Ty, V); + llvm_unreachable("Can only constant fold fp128"); +} +#endif + /// Clear the floating-point exception state. inline void llvm_fenv_clearexcept() { #if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT @@ -1781,6 +1789,20 @@ Constant *ConstantFoldFP(double (*NativeFP)(double), const APFloat &V, return GetConstantFoldFPValue(Result, Ty); } +#if defined(HAS_IEE754_FLOAT128) +Constant *ConstantFoldFP128(long double (*NativeFP)(long double), + const APFloat &V, Type *Ty) { + llvm_fenv_clearexcept(); + __float128 Result = NativeFP(V.convertToQuad()); + if (llvm_fenv_testexcept()) { + llvm_fenv_clearexcept(); + return nullptr; + } + + return GetConstantFoldFPValue128(Result, Ty); +} +#endif + Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), const APFloat &V, const APFloat &W, Type *Ty) { llvm_fenv_clearexcept(); @@ -2102,12 +2124,15 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) if (Ty->isFP128Ty()) { - switch (IntrinsicID) { - default: - return nullptr; - case Intrinsic::log: - return ConstantFP::get(Ty, logf128(Op->getValueAPF().convertToQuad())); + if (IntrinsicID == Intrinsic::log) { + __float128 Result = logf128(Op->getValueAPF().convertToQuad()); + return GetConstantFoldFPValue128(Result, Ty); } + + LibFunc Fp128Func = NotLibFunc; + if (TLI->getLibFunc(Name, Fp128Func) && TLI->has(Fp128Func) && + Fp128Func == LibFunc_logl) + return ConstantFoldFP128(logf128, Op->getValueAPF(), Ty); } #endif @@ -2368,6 +2393,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, // TODO: What about hosts that lack a C99 library? return ConstantFoldFP(log10, APF, Ty); break; + case LibFunc_logl: + return nullptr; case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_rint: diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll b/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll index da56997f6938..1f8e1d377f93 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll @@ -3,6 +3,7 @@ ; REQUIRES: has_logf128 declare fp128 @llvm.log.f128(fp128) +declare fp128 @logl(fp128) define fp128 @log_e_64(){ ; CHECK-LABEL: define fp128 @log_e_64() { @@ -124,3 +125,49 @@ define <2 x fp128> @log_e_negative_2_vector(){ %A = call <2 x fp128> @llvm.log.v2f128(<2 x fp128> ) ret <2 x fp128> %A } + +define fp128 @logl_e_64(){ +; CHECK-LABEL: define fp128 @logl_e_64() { +; CHECK-NEXT: [[A:%.*]] = call fp128 @logl(fp128 noundef 0xL00000000000000004005000000000000) +; CHECK-NEXT: ret fp128 0xL300000000000000040010A2B23F3BAB7 +; + %A = call fp128 @logl(fp128 noundef 0xL00000000000000004005000000000000) + ret fp128 %A +} + +define fp128 @logl_e_0(){ +; CHECK-LABEL: define fp128 @logl_e_0() { +; CHECK-NEXT: [[A:%.*]] = call fp128 @logl(fp128 noundef 0xL00000000000000000000000000000000) +; CHECK-NEXT: ret fp128 [[A]] +; + %A = call fp128 @logl(fp128 noundef 0xL00000000000000000000000000000000) + ret fp128 %A +} + +define fp128 @logl_e_infinity(){ +; CHECK-LABEL: define fp128 @logl_e_infinity() { +; CHECK-NEXT: [[A:%.*]] = call fp128 @logl(fp128 noundef 0xL00000000000000007FFF000000000000) +; CHECK-NEXT: ret fp128 0xL00000000000000007FFF000000000000 +; + %A = call fp128 @logl(fp128 noundef 0xL00000000000000007FFF000000000000) + ret fp128 %A +} + +define fp128 @logl_e_nan(){ +; CHECK-LABEL: define fp128 @logl_e_nan() { +; CHECK-NEXT: [[A:%.*]] = call fp128 @logl(fp128 noundef 0xL00000000000000007FFF000000000001) +; CHECK-NEXT: ret fp128 [[A]] +; + %A = call fp128 @logl(fp128 noundef 0xL00000000000000007FFF000000000001) + ret fp128 %A +} + + +define fp128 @logl_e_negative_2(){ +; CHECK-LABEL: define fp128 @logl_e_negative_2() { +; CHECK-NEXT: [[A:%.*]] = call fp128 @logl(fp128 noundef 0xL0000000000000000C000000000000000) +; CHECK-NEXT: ret fp128 [[A]] +; + %A = call fp128 @logl(fp128 noundef 0xL0000000000000000C000000000000000) + ret fp128 %A +} -- Gitee From 153e13af9216238b7ccb2e5b7a9c62e3e53767ed Mon Sep 17 00:00:00 2001 From: llvmssh Date: Fri, 6 Jun 2025 19:25:22 +0800 Subject: [PATCH 3/3] Constant fold logl call --- llvm/include/llvm/Support/float128.h | 4 ++++ llvm/lib/Analysis/ConstantFolding.cpp | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/Support/float128.h b/llvm/include/llvm/Support/float128.h index e15a98dc5a67..8887cd2bad7a 100644 --- a/llvm/include/llvm/Support/float128.h +++ b/llvm/include/llvm/Support/float128.h @@ -20,6 +20,10 @@ typedef __float128 float128; (defined(__GNUC__) || defined(__GNUG__)) #define HAS_IEE754_FLOAT128 typedef _Float128 float128; +#elif defined(__aarch64__) && defined(__linux__) && \ + !defined(__LONG_DOUBLE_IBM128__) +#define HAS_IEE754_FLOAT128 +typedef long double float128; #endif } // namespace llvm diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 47c910b89dbd..449de7ce314d 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -62,6 +62,11 @@ using namespace llvm; +static cl::opt +EnableLoglConstantFold("enable-logl-constant-fold", + cl::desc("Enable logl constant fold."), + cl::init(false), cl::Hidden); + namespace { //===----------------------------------------------------------------------===// @@ -1750,7 +1755,7 @@ Constant *GetConstantFoldFPValue(double V, Type *Ty) { } #if defined(HAS_IEE754_FLOAT128) -Constant *GetConstantFoldFPValue128(__float128 V, Type *Ty) { +Constant *GetConstantFoldFPValue128(float128 V, Type *Ty) { if (Ty->isFP128Ty()) return ConstantFP::get(Ty, V); llvm_unreachable("Can only constant fold fp128"); @@ -1790,10 +1795,10 @@ Constant *ConstantFoldFP(double (*NativeFP)(double), const APFloat &V, } #if defined(HAS_IEE754_FLOAT128) -Constant *ConstantFoldFP128(long double (*NativeFP)(long double), +Constant *ConstantFoldFP128(float128 (*NativeFP)(float128), const APFloat &V, Type *Ty) { llvm_fenv_clearexcept(); - __float128 Result = NativeFP(V.convertToQuad()); + float128 Result = NativeFP(V.convertToQuad()); if (llvm_fenv_testexcept()) { llvm_fenv_clearexcept(); return nullptr; @@ -2125,14 +2130,16 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) if (Ty->isFP128Ty()) { if (IntrinsicID == Intrinsic::log) { - __float128 Result = logf128(Op->getValueAPF().convertToQuad()); - return GetConstantFoldFPValue128(Result, Ty); + float128 Result = logf128(Op->getValueAPF().convertToQuad()); + if (EnableLoglConstantFold) + return GetConstantFoldFPValue128(Result, Ty); } LibFunc Fp128Func = NotLibFunc; if (TLI->getLibFunc(Name, Fp128Func) && TLI->has(Fp128Func) && Fp128Func == LibFunc_logl) - return ConstantFoldFP128(logf128, Op->getValueAPF(), Ty); + if (EnableLoglConstantFold) + return ConstantFoldFP128(logf128, Op->getValueAPF(), Ty); } #endif -- Gitee