Skip to content

Commit 86174cc

Browse files
committed
[APFloat] Add exp function for APFloat::IEEESsingle using expf implementation from LLVM libc.
1 parent b663e56 commit 86174cc

File tree

7 files changed

+79
-1
lines changed

7 files changed

+79
-1
lines changed

llvm/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,17 @@ endif()
659659

660660
set(LLVM_ENABLE_Z3_SOLVER_DEFAULT "${Z3_FOUND}")
661661

662+
set(LLVM_INTEGRATE_LIBC "OFF" CACHE STRING "Use LLVM libc codes directly if available.")
663+
664+
if(LLVM_INTEGRATE_LIBC)
665+
message(STATUS "LLVM_INTEGRATE_LIBC is ${LLVM_INTEGRATE_LIBC}")
666+
include(FindLibcCommonUtils)
667+
if(NOT TARGET llvm-libc-common-utilities)
668+
message(STATUS "LLVM_INTEGRATE_LIBC is set but cannot find LLVM libc at ${libc_path}.")
669+
set(LLVM_INTEGRATE_LIBC OFF)
670+
endif()
671+
endif()
672+
662673

663674
if( LLVM_TARGETS_TO_BUILD STREQUAL "all" )
664675
set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} )

llvm/include/llvm/ADT/APFloat.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,7 @@ class APFloat : public APFloatBase {
15231523
friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
15241524
friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
15251525
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
1526+
friend APFloat exp(const APFloat &X, roundingMode RM);
15261527
friend IEEEFloat;
15271528
friend DoubleAPFloat;
15281529
};
@@ -1658,6 +1659,10 @@ inline APFloat maximumnum(const APFloat &A, const APFloat &B) {
16581659
return A < B ? B : A;
16591660
}
16601661

1662+
/// Implement IEEE 754-2019 exp functions.
1663+
LLVM_READONLY
1664+
APFloat exp(const APFloat &X, RoundingMode RM);
1665+
16611666
inline raw_ostream &operator<<(raw_ostream &OS, const APFloat &V) {
16621667
V.print(OS);
16631668
return OS;

llvm/include/llvm/Config/llvm-config.h.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,7 @@
146146
coverage bugs, and to 0 otherwise. */
147147
#cmakedefine01 LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
148148

149+
/* Define if LLVM and clang uses LLVM libc for math computations. */
150+
#cmakedefine LLVM_INTEGRATE_LIBC
151+
149152
#endif

llvm/lib/Support/APFloat.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
#include <cstring>
2929
#include <limits.h>
3030

31+
#ifdef LLVM_INTEGRATE_LIBC
32+
// Shared headers from LLVM libc
33+
#include "shared/math.h"
34+
#endif // LLVM_INTEGRATE_LIBC
35+
3136
#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \
3237
do { \
3338
if (usesLayout<IEEEFloat>(getSemantics())) \
@@ -5601,6 +5606,35 @@ float APFloat::convertToFloat() const {
56015606
return Temp.getIEEE().convertToFloat();
56025607
}
56035608

5609+
#ifdef LLVM_INTEGRATE_LIBC
5610+
APFloat exp(const APFloat &X, RoundingMode rounding_mode) {
5611+
assert((&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) &&
5612+
"Float semantics is not IEEEsingle");
5613+
if (&X.getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) {
5614+
int current_rounding_mode = fegetround();
5615+
switch (rounding_mode) {
5616+
case APFloat::rmNearestTiesToEven:
5617+
fesetround(FE_TONEAREST);
5618+
break;
5619+
case APFloat::rmTowardPositive:
5620+
fesetround(FE_UPWARD);
5621+
break;
5622+
case APFloat::rmTowardNegative:
5623+
fesetround(FE_DOWNWARD);
5624+
break;
5625+
case APFloat::rmTowardZero:
5626+
fesetround(FE_TOWARDZERO);
5627+
break;
5628+
default:
5629+
}
5630+
float result = LIBC_NAMESPACE::shared::expf(X.convertToFloat());
5631+
fesetround(current_rounding_mode);
5632+
return APFloat(result);
5633+
}
5634+
llvm_unreachable("Unexpected semantics");
5635+
}
5636+
#endif // LLVM_INTEGRATE_LIBC
5637+
56045638
} // namespace llvm
56055639

56065640
#undef APFLOAT_DISPATCH_ON_SEMANTICS

llvm/lib/Support/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,9 @@ target_include_directories(LLVMSupport
384384
PRIVATE
385385
${LLVM_THIRD_PARTY_DIR}/siphash/include
386386
)
387+
388+
if(LLVM_INTEGRATE_LIBC)
389+
set_property(TARGET LLVMSupport PROPERTY CXX_STANDARD 17)
390+
target_include_directories(LLVMSupport PRIVATE "${LLVM_INCLUDE_DIR}/../../libc")
391+
target_compile_options(LLVMSupport PRIVATE "-Wno-c99-extensions") # _Complex warnings.
392+
endif()

llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ bool AMDGPULibCalls::evaluateScalarMathFunc(const FuncInfo &FInfo, double &Res0,
15401540
return true;
15411541

15421542
case AMDGPULibFunc::EI_EXP:
1543-
Res0 = exp(opr0);
1543+
Res0 = std::exp(opr0);
15441544
return true;
15451545

15461546
case AMDGPULibFunc::EI_EXP2:

llvm/unittests/ADT/APFloatTest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8356,4 +8356,23 @@ TEST(APFloatTest, hasSignBitInMSB) {
83568356
EXPECT_FALSE(APFloat::hasSignBitInMSB(APFloat::Float8E8M0FNU()));
83578357
}
83588358

8359+
#ifdef LLVM_INTEGRATE_LIBC
8360+
TEST(APFloatTest, expf) {
8361+
EXPECT_EQ(
8362+
1.0f,
8363+
llvm::exp(APFloat(0.0f), APFloat::rmNearestTiesToEven).convertToFloat());
8364+
EXPECT_EQ(
8365+
0x1.5bf0a8p1f,
8366+
llvm::exp(APFloat(1.0f), APFloat::rmNearestTiesToEven).convertToFloat());
8367+
EXPECT_EQ(
8368+
0x1.5bf0aap1f,
8369+
llvm::exp(APFloat(1.0f), APFloat::rmTowardPositive).convertToFloat());
8370+
EXPECT_EQ(
8371+
0x1.5bf0a8p1f,
8372+
llvm::exp(APFloat(1.0f), APFloat::rmTowardNegative).convertToFloat());
8373+
EXPECT_EQ(0x1.5bf0a8p1f,
8374+
llvm::exp(APFloat(1.0f), APFloat::rmTowardZero).convertToFloat());
8375+
}
8376+
#endif // LLVM_INTEGRATE_LIBC
8377+
83598378
} // namespace

0 commit comments

Comments
 (0)