Skip to content

Commit 1b0628e

Browse files
overmightylravenclaw
authored andcommitted
[libc][math][c23] Add f16sqrt{,l,f128} C23 math functions (llvm#96642)
Part of llvm#95250.
1 parent d53a438 commit 1b0628e

24 files changed

+352
-124
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
510510
libc.src.math.f16div
511511
libc.src.math.f16divf
512512
libc.src.math.f16fmaf
513+
libc.src.math.f16sqrt
513514
libc.src.math.f16sqrtf
514515
libc.src.math.fabsf16
515516
libc.src.math.fdimf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,9 @@ if(LIBC_TYPES_HAS_FLOAT16)
543543
libc.src.math.f16fma
544544
libc.src.math.f16fmaf
545545
libc.src.math.f16fmal
546+
libc.src.math.f16sqrt
546547
libc.src.math.f16sqrtf
548+
libc.src.math.f16sqrtl
547549
libc.src.math.fabsf16
548550
libc.src.math.fdimf16
549551
libc.src.math.floorf16
@@ -596,8 +598,9 @@ if(LIBC_TYPES_HAS_FLOAT16)
596598
if(LIBC_TYPES_HAS_FLOAT128)
597599
list(APPEND TARGET_LIBM_ENTRYPOINTS
598600
# math.h C23 mixed _Float16 and _Float128 entrypoints
599-
libc.src.math.f16fmaf128
600601
libc.src.math.f16divf128
602+
libc.src.math.f16fmaf128
603+
libc.src.math.f16sqrtf128
601604
)
602605
endif()
603606
endif()

libc/docs/math/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ Higher Math Functions
292292
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
293293
| fma | |check| | |check| | | | | 7.12.13.1 | F.10.10.1 |
294294
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
295-
| f16sqrt | |check| | | | N/A | | 7.12.14.6 | F.10.11 |
295+
| f16sqrt | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.6 | F.10.11 |
296296
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
297297
| fsqrt | N/A | | | N/A | | 7.12.14.6 | F.10.11 |
298298
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/spec/llvm_libc_ext.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
6060
GuardedFunctionSpec<"f16div", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
6161
GuardedFunctionSpec<"f16divf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
6262
GuardedFunctionSpec<"f16divl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
63+
64+
GuardedFunctionSpec<"f16sqrt", RetValSpec<Float16Type>, [ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
65+
GuardedFunctionSpec<"f16sqrtf", RetValSpec<Float16Type>, [ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
66+
GuardedFunctionSpec<"f16sqrtl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
6367
]
6468
>;
6569

libc/spec/stdc.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ def StdC : StandardSpec<"stdc"> {
731731

732732
GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
733733

734-
GuardedFunctionSpec<"f16sqrtf", RetValSpec<Float16Type>, [ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
734+
GuardedFunctionSpec<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
735735
]
736736
>;
737737

libc/src/__support/FPUtil/generic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_header_library(
88
libc.src.__support.common
99
libc.src.__support.CPP.bit
1010
libc.src.__support.CPP.type_traits
11+
libc.src.__support.FPUtil.dyadic_float
1112
libc.src.__support.FPUtil.fenv_impl
1213
libc.src.__support.FPUtil.fp_bits
1314
libc.src.__support.FPUtil.rounding_mode

libc/src/__support/FPUtil/generic/sqrt.h

Lines changed: 15 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "src/__support/CPP/type_traits.h"
1515
#include "src/__support/FPUtil/FEnvImpl.h"
1616
#include "src/__support/FPUtil/FPBits.h"
17-
#include "src/__support/FPUtil/rounding_mode.h"
17+
#include "src/__support/FPUtil/dyadic_float.h"
1818
#include "src/__support/common.h"
1919
#include "src/__support/uint128.h"
2020

@@ -78,16 +78,14 @@ sqrt(InType x) {
7878
return x86::sqrt(x);
7979
} else {
8080
// IEEE floating points formats.
81-
using OutFPBits = typename fputil::FPBits<OutType>;
82-
using OutStorageType = typename OutFPBits::StorageType;
83-
using InFPBits = typename fputil::FPBits<InType>;
81+
using OutFPBits = FPBits<OutType>;
82+
using InFPBits = FPBits<InType>;
8483
using InStorageType = typename InFPBits::StorageType;
84+
using DyadicFloat =
85+
DyadicFloat<cpp::bit_ceil(static_cast<size_t>(InFPBits::STORAGE_LEN))>;
86+
8587
constexpr InStorageType ONE = InStorageType(1) << InFPBits::FRACTION_LEN;
8688
constexpr auto FLT_NAN = OutFPBits::quiet_nan().get_val();
87-
constexpr int EXTRA_FRACTION_LEN =
88-
InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
89-
constexpr InStorageType EXTRA_FRACTION_MASK =
90-
(InStorageType(1) << EXTRA_FRACTION_LEN) - 1;
9189

9290
InFPBits bits(x);
9391

@@ -135,6 +133,7 @@ sqrt(InType x) {
135133
InStorageType y = ONE;
136134
InStorageType r = x_mant - ONE;
137135

136+
// TODO: Reduce iteration count to OutFPBits::FRACTION_LEN + 2 or + 3.
138137
for (InStorageType current_bit = ONE >> 1; current_bit;
139138
current_bit >>= 1) {
140139
r <<= 1;
@@ -146,91 +145,19 @@ sqrt(InType x) {
146145
}
147146

148147
// We compute one more iteration in order to round correctly.
149-
bool lsb = (y & (InStorageType(1) << EXTRA_FRACTION_LEN)) !=
150-
0; // Least significant bit
151-
bool rb = false; // Round bit
152148
r <<= 2;
153-
InStorageType tmp = (y << 2) + 1;
149+
y <<= 2;
150+
InStorageType tmp = y + 1;
154151
if (r >= tmp) {
155152
r -= tmp;
156-
rb = true;
157-
}
158-
159-
bool sticky = false;
160-
161-
if constexpr (EXTRA_FRACTION_LEN > 0) {
162-
sticky = rb || (y & EXTRA_FRACTION_MASK) != 0;
163-
rb = (y & (InStorageType(1) << (EXTRA_FRACTION_LEN - 1))) != 0;
164-
}
165-
166-
// Remove hidden bit and append the exponent field.
167-
x_exp = ((x_exp >> 1) + OutFPBits::EXP_BIAS);
168-
169-
OutStorageType y_out = static_cast<OutStorageType>(
170-
((y - ONE) >> EXTRA_FRACTION_LEN) |
171-
(static_cast<OutStorageType>(x_exp) << OutFPBits::FRACTION_LEN));
172-
173-
if constexpr (EXTRA_FRACTION_LEN > 0) {
174-
if (x_exp >= OutFPBits::MAX_BIASED_EXPONENT) {
175-
switch (quick_get_round()) {
176-
case FE_TONEAREST:
177-
case FE_UPWARD:
178-
return OutFPBits::inf().get_val();
179-
default:
180-
return OutFPBits::max_normal().get_val();
181-
}
182-
}
183-
184-
if (x_exp <
185-
-OutFPBits::EXP_BIAS - OutFPBits::SIG_LEN + EXTRA_FRACTION_LEN) {
186-
switch (quick_get_round()) {
187-
case FE_UPWARD:
188-
return OutFPBits::min_subnormal().get_val();
189-
default:
190-
return OutType(0.0);
191-
}
192-
}
193-
194-
if (x_exp <= 0) {
195-
int underflow_extra_fraction_len = EXTRA_FRACTION_LEN - x_exp + 1;
196-
InStorageType underflow_extra_fraction_mask =
197-
(InStorageType(1) << underflow_extra_fraction_len) - 1;
198-
199-
rb = (y & (InStorageType(1) << (underflow_extra_fraction_len - 1))) !=
200-
0;
201-
OutStorageType subnormal_mant =
202-
static_cast<OutStorageType>(y >> underflow_extra_fraction_len);
203-
lsb = (subnormal_mant & 1) != 0;
204-
sticky = sticky || (y & underflow_extra_fraction_mask) != 0;
205-
206-
switch (quick_get_round()) {
207-
case FE_TONEAREST:
208-
if (rb && (lsb || sticky))
209-
++subnormal_mant;
210-
break;
211-
case FE_UPWARD:
212-
if (rb || sticky)
213-
++subnormal_mant;
214-
break;
215-
}
216-
217-
return cpp::bit_cast<OutType>(subnormal_mant);
218-
}
219-
}
220-
221-
switch (quick_get_round()) {
222-
case FE_TONEAREST:
223-
// Round to nearest, ties to even
224-
if (rb && (lsb || (r != 0)))
225-
++y_out;
226-
break;
227-
case FE_UPWARD:
228-
if (rb || (r != 0) || sticky)
229-
++y_out;
230-
break;
153+
// Rounding bit.
154+
y |= 2;
231155
}
156+
// Sticky bit.
157+
y |= static_cast<unsigned int>(r != 0);
232158

233-
return cpp::bit_cast<OutType>(y_out);
159+
DyadicFloat yd(Sign::POS, (x_exp >> 1) - 2 - InFPBits::FRACTION_LEN, y);
160+
return yd.template as<OutType, /*ShouldSignalExceptions=*/true>();
234161
}
235162
}
236163
}

libc/src/math/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,10 @@ add_math_entrypoint_object(f16fmaf)
109109
add_math_entrypoint_object(f16fmal)
110110
add_math_entrypoint_object(f16fmaf128)
111111

112+
add_math_entrypoint_object(f16sqrt)
112113
add_math_entrypoint_object(f16sqrtf)
114+
add_math_entrypoint_object(f16sqrtl)
115+
add_math_entrypoint_object(f16sqrtf128)
113116

114117
add_math_entrypoint_object(fabs)
115118
add_math_entrypoint_object(fabsf)

libc/src/math/f16sqrt.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for f16sqrt -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_MATH_F16SQRT_H
10+
#define LLVM_LIBC_SRC_MATH_F16SQRT_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 f16sqrt(double x);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_F16SQRT_H

libc/src/math/f16sqrtf128.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for f16sqrtf128 -------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_MATH_F16SQRTF128_H
10+
#define LLVM_LIBC_SRC_MATH_F16SQRTF128_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 f16sqrtf128(float128 x);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_F16SQRTF128_H

libc/src/math/f16sqrtl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for f16sqrtl ----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_MATH_F16SQRTL_H
10+
#define LLVM_LIBC_SRC_MATH_F16SQRTL_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 f16sqrtl(long double x);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_F16SQRTL_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3880,6 +3880,19 @@ add_entrypoint_object(
38803880
-O3
38813881
)
38823882

3883+
add_entrypoint_object(
3884+
f16sqrt
3885+
SRCS
3886+
f16sqrt.cpp
3887+
HDRS
3888+
../f16sqrt.h
3889+
DEPENDS
3890+
libc.src.__support.macros.properties.types
3891+
libc.src.__support.FPUtil.sqrt
3892+
COMPILE_OPTIONS
3893+
-O3
3894+
)
3895+
38833896
add_entrypoint_object(
38843897
f16sqrtf
38853898
SRCS
@@ -3892,3 +3905,29 @@ add_entrypoint_object(
38923905
COMPILE_OPTIONS
38933906
-O3
38943907
)
3908+
3909+
add_entrypoint_object(
3910+
f16sqrtl
3911+
SRCS
3912+
f16sqrtl.cpp
3913+
HDRS
3914+
../f16sqrtl.h
3915+
DEPENDS
3916+
libc.src.__support.macros.properties.types
3917+
libc.src.__support.FPUtil.sqrt
3918+
COMPILE_OPTIONS
3919+
-O3
3920+
)
3921+
3922+
add_entrypoint_object(
3923+
f16sqrtf128
3924+
SRCS
3925+
f16sqrtf128.cpp
3926+
HDRS
3927+
../f16sqrtf128.h
3928+
DEPENDS
3929+
libc.src.__support.macros.properties.types
3930+
libc.src.__support.FPUtil.sqrt
3931+
COMPILE_OPTIONS
3932+
-O3
3933+
)

libc/src/math/generic/f16sqrt.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of f16sqrt function --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/math/f16sqrt.h"
10+
#include "src/__support/FPUtil/sqrt.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, f16sqrt, (double x)) {
16+
return fputil::sqrt<float16>(x);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/math/generic/f16sqrtf128.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of f16sqrtf128 function ----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/math/f16sqrtf128.h"
10+
#include "src/__support/FPUtil/sqrt.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, f16sqrtf128, (float128 x)) {
16+
return fputil::sqrt<float16>(x);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/math/generic/f16sqrtl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of f16sqrtl function -------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/math/f16sqrtl.h"
10+
#include "src/__support/FPUtil/sqrt.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, f16sqrtl, (long double x)) {
16+
return fputil::sqrt<float16>(x);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)