-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Enable logf128 constant folding for hosts with 128bit long double #96287
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
Changes from 4 commits
4cc6905
97a0b20
94c6914
422fed8
613f6a4
5705316
6ceda72
cc0a937
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,64 @@ 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) | ||
|
|
||
| # 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) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using try_run tends to lead to strange results with cross-compiling; do we really need it here? _Float128/__float128 should always mean what we want it to, and we can use
__LDBL_MANT_DIG__for long double.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x86 hosts with 80bit long doubles can compile logf128 but will return an error code.
__LDBL_MANT_DIG__does work fine for hosts with 128bit long doubles, but this will also disable the fold for x86 targets with fp80 that can still perform an accurate fold with __float128 types. I'm struggling to think of an alternative way to select the most valid and best type at compile time to use without try_run based on the following criteria:Logf128 symbol availability
Logf128 function prototype availability
Long double total size (Needs to be 16 bytes)
Long double mantissa size (Rules out fp80)
GCC version(12+ won't accept anything other than _Float128 for logf128)
If we're compiling with GCC or Clang (Clang needs to declare the logf128 prototype)
__float128 availability
_Float128 availability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You only need to check
__LDBL_MANT_DIG__if you're trying to use the typelong double. You can assume__float128and_Float128have the right format.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Firstly, thanks for your patience with this review.
I'm still unsure how to differentiate in a header file between
_Float128andlong doublefor GCC12+, where trying to pass in anything other than GCC 12+'s dedicated _Float128 type will cause a compilation error. A condition along the lines ofwill be valid for GCC12 and GCC11 while it is actually only valid for GCC11: long double isn't valid for logf128 anymore after GCC12, but the host still has a long double mantissa size of 113.
I think you're suggesting I do
typedef decltype(logf128(0.)) float128;only when long double is known to have a mantissa of 113, and worry about hosts that have access to float128 but have a manstissa of not 113 in a following patch. I just wanted to double check.