Skip to content

Commit af0f85c

Browse files
authored
[libc][math] Do not use float16 basic operations in hypotf16. (#155177)
Compiler runtimes for float16 basic operations might not be correctly rounded for all rounding modes.
1 parent 45f3263 commit af0f85c

File tree

4 files changed

+21
-9
lines changed

4 files changed

+21
-9
lines changed

libc/src/__support/FPUtil/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ add_header_library(
231231
Hypot.h
232232
DEPENDS
233233
.basic_operations
234+
.cast
234235
.fenv_impl
235236
.fp_bits
236237
.rounding_mode

libc/src/__support/FPUtil/Hypot.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "BasicOperations.h"
1313
#include "FEnvImpl.h"
1414
#include "FPBits.h"
15+
#include "cast.h"
1516
#include "rounding_mode.h"
1617
#include "src/__support/CPP/bit.h"
1718
#include "src/__support/CPP/type_traits.h"
@@ -133,8 +134,18 @@ LIBC_INLINE T hypot(T x, T y) {
133134
uint16_t a_exp = a_bits.get_biased_exponent();
134135
uint16_t b_exp = b_bits.get_biased_exponent();
135136

136-
if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0))
137-
return x_abs.get_val() + y_abs.get_val();
137+
if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0)) {
138+
#ifdef LIBC_TYPES_HAS_FLOAT16
139+
if constexpr (cpp::is_same_v<T, float16>) {
140+
// Compiler runtime for basic operations of float16 might not be correctly
141+
// rounded for all rounding modes.
142+
float af = fputil::cast<float>(x_abs.get_val());
143+
float bf = fputil::cast<float>(y_abs.get_val());
144+
return fputil::cast<float16>(af + bf);
145+
} else
146+
#endif // LIBC_TYPES_HAS_FLOAT16
147+
return x_abs.get_val() + y_abs.get_val();
148+
}
138149

139150
uint64_t out_exp = a_exp;
140151
StorageType a_mant = a_bits.get_mantissa();

libc/src/math/generic/hypotf16.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,15 @@ LLVM_LIBC_FUNCTION(float16, hypotf16, (float16 x, float16 y)) {
4848
return a_bits.get_val();
4949
}
5050

51-
// TODO: Investigate why replacing the return line below with:
52-
// return x_bits.get_val() + y_bits.get_val();
53-
// fails the hypotf16 smoke tests.
51+
float af = fputil::cast<float>(a_bits.get_val());
52+
float bf = fputil::cast<float>(b_bits.get_val());
53+
54+
// Compiler runtime basic operations for float16 might not be correctly
55+
// rounded for all rounding modes.
5456
if (LIBC_UNLIKELY(a_u - b_u >=
5557
static_cast<uint16_t>((FPBits::FRACTION_LEN + 2)
5658
<< FPBits::FRACTION_LEN)))
57-
return a_bits.get_val() + b_bits.get_val();
58-
59-
float af = fputil::cast<float>(a_bits.get_val());
60-
float bf = fputil::cast<float>(b_bits.get_val());
59+
return fputil::cast<float16>(af + bf);
6160

6261
// These squares are exact.
6362
float a_sq = af * af;

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,7 @@ libc_support_library(
12301230
":__support_cpp_bit",
12311231
":__support_cpp_type_traits",
12321232
":__support_fputil_basic_operations",
1233+
":__support_fputil_cast",
12331234
":__support_fputil_fenv_impl",
12341235
":__support_fputil_fp_bits",
12351236
":__support_fputil_rounding_mode",

0 commit comments

Comments
 (0)