Skip to content

Constant Fold Logf128 calls #84501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,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.")
Expand Down
11 changes: 11 additions & 0 deletions llvm/cmake/config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,17 @@ else()
set(LLVM_ENABLE_TERMINFO 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)
Expand Down
13 changes: 13 additions & 0 deletions llvm/include/llvm/ADT/APFloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <memory>

#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \
Expand Down Expand Up @@ -354,6 +355,9 @@ class IEEEFloat final : public APFloatBase {
Expected<opStatus> convertFromString(StringRef, roundingMode);
APInt bitcastToAPInt() const;
double convertToDouble() const;
#ifdef __FLOAT128__
float128 convertToQuad() const;
#endif
float convertToFloat() const;

/// @}
Expand Down Expand Up @@ -1218,6 +1222,15 @@ 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 __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
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/ADT/APInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/float128.h"
#include <cassert>
#include <climits>
#include <cstring>
Expand Down Expand Up @@ -1670,6 +1671,13 @@ class [[nodiscard]] APInt {
/// any bit width. Exactly 64 bits will be translated.
double bitsToDouble() const { return llvm::bit_cast<double>(getWord(0)); }

#ifdef __FLOAT128__
float128 bitsToQuad() const {
__uint128_t ul = ((__uint128_t)U.pVal[1] << 64) + U.pVal[0];
return llvm::bit_cast<float128>(ul);
}
#endif

/// Converts APInt bits to a float
///
/// The conversion does not do a translation from integer to float, it just
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Config/llvm-config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,7 @@
/* Define if plugins enabled */
#cmakedefine LLVM_ENABLE_PLUGINS

/* Define if logf128 is available */
#cmakedefine LLVM_HAS_LOGF128

#endif
21 changes: 21 additions & 0 deletions llvm/include/llvm/Support/float128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- 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__)
typedef __float128 float128;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

namespace llvm?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

#elif defined(__FLOAT128__) && (defined(__GNUC__) || defined(__GNUG__))
typedef _Float128 float128;
#endif

} // namespace llvm
#endif // LLVM_FLOAT128
6 changes: 6 additions & 0 deletions llvm/lib/Analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,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()
11 changes: 11 additions & 0 deletions llvm/lib/Analysis/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,17 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
if (IntrinsicID == Intrinsic::canonicalize)
return constantFoldCanonicalize(Ty, Call, U);

#if defined(__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;

Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Support/APFloat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3670,6 +3670,15 @@ double IEEEFloat::convertToDouble() const {
return api.bitsToDouble();
}

#ifdef __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")
Expand Down Expand Up @@ -5265,6 +5274,21 @@ double APFloat::convertToDouble() const {
return Temp.getIEEE().convertToDouble();
}

#ifdef __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();
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ llvm_canonicalize_cmake_booleans(
LLVM_INCLUDE_DXIL_TESTS
LLVM_TOOL_LLVM_DRIVER_BUILD
LLVM_INCLUDE_SPIRV_TOOLS_TESTS
LLVM_HAS_LOGF128
)

configure_lit_site_cfg(
Expand Down
126 changes: 126 additions & 0 deletions llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll
Original file line number Diff line number Diff line change
@@ -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
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test inf/nan/zero

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.


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
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test vectors?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean, sorry. I initially thought you meant the log function can take a vector type parameter, but after checking https://llvm.org/docs/LangRef.html#llvm-log-intrinsic I can't see one.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

define <2 x fp128> @log_e_negative_2(){
  %A = call <2 x fp128> @llvm.log.v2f128(<2 x fp128> <fp128 0xL0000000000000000C000000000000000, fp128 0xL0000000000000000C000000000000001>)
  ret <2 x fp128> %A
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've added that test now.


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> <fp128 0xL00000000000000007FFF800000000000, fp128 0xL00000000000000007FFF800000000000>
;
%A = call <2 x fp128> @llvm.log.v2f128(<2 x fp128> <fp128 0xL0000000000000000C000000000000000, fp128 0xL0000000000000000C000000000000001>)
ret <2 x fp128> %A
}
3 changes: 3 additions & 0 deletions llvm/test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,6 @@ def have_ld64_plugin_support():
# "OBJECT_MODE" to 'any' by default on AIX OS.
if "system-aix" in config.available_features:
config.environment["OBJECT_MODE"] = "any"

if config.has_logf128:
config.available_features.add("has_logf128")
1 change: 1 addition & 0 deletions llvm/test/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ config.reverse_iteration = @LLVM_ENABLE_REVERSE_ITERATION@
config.dxil_tests = @LLVM_INCLUDE_DXIL_TESTS@
config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@
config.spirv_tools_tests = @LLVM_INCLUDE_SPIRV_TOOLS_TESTS@
config.has_logf128 = @LLVM_HAS_LOGF128@

import lit.llvm
lit.llvm.initialize(lit_config, config)
Expand Down
6 changes: 6 additions & 0 deletions llvm/unittests/Analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,11 @@ if(NOT WIN32)
export_executable_symbols_for_plugins(AnalysisTests)
endif()

include(CheckCXXSymbolExists)
check_cxx_symbol_exists(logf128 math.h HAS_LOGF128)
if(HAS_LOGF128)
target_compile_definitions(AnalysisTests PRIVATE HAS_LOGF128)
endif()

add_subdirectory(InlineAdvisorPlugin)
add_subdirectory(InlineOrderPlugin)