Skip to content

Commit 337b771

Browse files
Revert "[libc][NFC] Refactor FPBits and remove LongDoubleBits specialization (#78192)" (#78329)
This reverts commit fdbf255. Causes build breakage on 32b arm (see reports: #78192). These are reproducible for the 32b arm baremetal target on x86 hosts as well.
1 parent 1847846 commit 337b771

File tree

8 files changed

+282
-618
lines changed

8 files changed

+282
-618
lines changed

libc/src/__support/FPUtil/FPBits.h

Lines changed: 91 additions & 352 deletions
Large diffs are not rendered by default.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ LIBC_INLINE long double sqrt(long double x) {
131131
out.set_implicit_bit(1);
132132
out.set_mantissa((y & (ONE - 1)));
133133

134-
return out.get_val();
134+
return out;
135135
}
136136
}
137137
#endif // LIBC_LONG_DOUBLE_IS_X86_FLOAT80
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
//===-- Bit representation of x86 long double numbers -----------*- 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___SUPPORT_FPUTIL_X86_64_LONGDOUBLEBITS_H
10+
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_LONGDOUBLEBITS_H
11+
12+
#include "src/__support/CPP/bit.h"
13+
#include "src/__support/UInt128.h"
14+
#include "src/__support/common.h"
15+
#include "src/__support/macros/attributes.h" // LIBC_INLINE
16+
#include "src/__support/macros/properties/architectures.h"
17+
18+
#if !defined(LIBC_TARGET_ARCH_IS_X86)
19+
#error "Invalid include"
20+
#endif
21+
22+
#include "src/__support/FPUtil/FPBits.h"
23+
24+
#include <stdint.h>
25+
26+
namespace LIBC_NAMESPACE {
27+
namespace fputil {
28+
29+
template <>
30+
struct FPBits<long double> : public internal::FPRep<FPType::X86_Binary80> {
31+
using UP = internal::FPRep<FPType::X86_Binary80>;
32+
using StorageType = typename UP::StorageType;
33+
34+
private:
35+
using UP::bits;
36+
using UP::EXP_SIG_MASK;
37+
using UP::QUIET_NAN_MASK;
38+
39+
public:
40+
// Constants.
41+
static constexpr int MAX_BIASED_EXPONENT = (1 << EXP_LEN) - 1;
42+
// The x86 80 bit float represents the leading digit of the mantissa
43+
// explicitly. This is the mask for that bit.
44+
static constexpr StorageType EXPLICIT_BIT_MASK = StorageType(1)
45+
<< FRACTION_LEN;
46+
// The X80 significand is made of an explicit bit and the fractional part.
47+
static_assert((EXPLICIT_BIT_MASK & FRACTION_MASK) == 0,
48+
"the explicit bit and the fractional part should not overlap");
49+
static_assert((EXPLICIT_BIT_MASK | FRACTION_MASK) == SIG_MASK,
50+
"the explicit bit and the fractional part should cover the "
51+
"whole significand");
52+
static constexpr StorageType MIN_SUBNORMAL = StorageType(1);
53+
// Subnormal numbers include the implicit bit in x86 long double formats.
54+
static constexpr StorageType MAX_SUBNORMAL = FRACTION_MASK;
55+
static constexpr StorageType MIN_NORMAL =
56+
(StorageType(1) << SIG_LEN) | EXPLICIT_BIT_MASK;
57+
static constexpr StorageType MAX_NORMAL =
58+
(StorageType(MAX_BIASED_EXPONENT - 1) << SIG_LEN) | SIG_MASK;
59+
60+
// Constructors.
61+
LIBC_INLINE constexpr FPBits() = default;
62+
63+
template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) {
64+
using Unqual = typename cpp::remove_cv_t<XType>;
65+
if constexpr (cpp::is_same_v<Unqual, long double>) {
66+
bits = cpp::bit_cast<StorageType>(x);
67+
} else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
68+
bits = x;
69+
} else {
70+
// We don't want accidental type promotions/conversions, so we require
71+
// exact type match.
72+
static_assert(cpp::always_false<XType>);
73+
}
74+
}
75+
76+
// Floating-point conversions.
77+
LIBC_INLINE constexpr long double get_val() const {
78+
return cpp::bit_cast<long double>(bits);
79+
}
80+
81+
LIBC_INLINE constexpr operator long double() const {
82+
return cpp::bit_cast<long double>(bits);
83+
}
84+
85+
LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
86+
return bits & SIG_MASK;
87+
}
88+
89+
LIBC_INLINE constexpr bool get_implicit_bit() const {
90+
return bits & EXPLICIT_BIT_MASK;
91+
}
92+
93+
LIBC_INLINE constexpr void set_implicit_bit(bool implicitVal) {
94+
if (get_implicit_bit() != implicitVal)
95+
bits ^= EXPLICIT_BIT_MASK;
96+
}
97+
98+
LIBC_INLINE constexpr bool is_inf() const {
99+
return get_biased_exponent() == MAX_BIASED_EXPONENT &&
100+
get_mantissa() == 0 && get_implicit_bit() == 1;
101+
}
102+
103+
LIBC_INLINE constexpr bool is_nan() const {
104+
if (get_biased_exponent() == MAX_BIASED_EXPONENT) {
105+
return (get_implicit_bit() == 0) || get_mantissa() != 0;
106+
} else if (get_biased_exponent() != 0) {
107+
return get_implicit_bit() == 0;
108+
}
109+
return false;
110+
}
111+
112+
LIBC_INLINE constexpr bool is_inf_or_nan() const {
113+
return (get_biased_exponent() == MAX_BIASED_EXPONENT) ||
114+
(get_biased_exponent() != 0 && get_implicit_bit() == 0);
115+
}
116+
117+
LIBC_INLINE constexpr bool is_quiet_nan() const {
118+
return (bits & EXP_SIG_MASK) >= (EXP_MASK | QUIET_NAN_MASK);
119+
}
120+
121+
// Methods below this are used by tests.
122+
123+
LIBC_INLINE static constexpr long double zero(bool sign = false) {
124+
StorageType rep = (sign ? SIGN_MASK : StorageType(0)) // sign
125+
| 0 // exponent
126+
| 0 // explicit bit
127+
| 0; // mantissa
128+
return FPBits(rep).get_val();
129+
}
130+
131+
LIBC_INLINE static constexpr long double neg_zero() { return zero(true); }
132+
133+
LIBC_INLINE static constexpr long double inf(bool sign = false) {
134+
StorageType rep = (sign ? SIGN_MASK : StorageType(0)) // sign
135+
| EXP_MASK // exponent
136+
| EXPLICIT_BIT_MASK // explicit bit
137+
| 0; // mantissa
138+
return FPBits(rep).get_val();
139+
}
140+
141+
LIBC_INLINE static constexpr long double neg_inf() { return inf(true); }
142+
143+
LIBC_INLINE static constexpr long double min_normal() {
144+
return FPBits(MIN_NORMAL).get_val();
145+
}
146+
147+
LIBC_INLINE static constexpr long double max_normal() {
148+
return FPBits(MAX_NORMAL).get_val();
149+
}
150+
151+
LIBC_INLINE static constexpr long double min_denormal() {
152+
return FPBits(MIN_SUBNORMAL).get_val();
153+
}
154+
155+
LIBC_INLINE static constexpr long double max_denormal() {
156+
return FPBits(MAX_SUBNORMAL).get_val();
157+
}
158+
159+
LIBC_INLINE static constexpr long double build_nan(StorageType v) {
160+
StorageType rep = 0 // sign
161+
| EXP_MASK // exponent
162+
| EXPLICIT_BIT_MASK // explicit bit
163+
| (v & FRACTION_MASK); // mantissa
164+
return FPBits(rep).get_val();
165+
}
166+
167+
LIBC_INLINE static constexpr long double build_quiet_nan(StorageType v) {
168+
return build_nan(QUIET_NAN_MASK | v);
169+
}
170+
};
171+
172+
static_assert(
173+
sizeof(FPBits<long double>) == sizeof(long double),
174+
"Internal long double representation does not match the machine format.");
175+
176+
} // namespace fputil
177+
} // namespace LIBC_NAMESPACE
178+
179+
#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_LONGDOUBLEBITS_H

libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
6161
from_bits.set_biased_exponent(from_bits.get_biased_exponent() + 1);
6262
if (from_bits.is_inf())
6363
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
64-
return from_bits.get_val();
64+
return from_bits;
6565
} else {
6666
++int_val;
6767
}
@@ -75,7 +75,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
7575
// from == 0 is handled separately so decrementing the exponent will not
7676
// lead to underflow.
7777
from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
78-
return from_bits.get_val();
78+
return from_bits;
7979
} else {
8080
--int_val;
8181
}
@@ -94,7 +94,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
9494
// from == 0 is handled separately so decrementing the exponent will not
9595
// lead to underflow.
9696
from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
97-
return from_bits.get_val();
97+
return from_bits;
9898
} else {
9999
--int_val;
100100
}
@@ -109,7 +109,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
109109
from_bits.set_biased_exponent(from_bits.get_biased_exponent() + 1);
110110
if (from_bits.is_inf())
111111
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
112-
return from_bits.get_val();
112+
return from_bits;
113113
} else {
114114
++int_val;
115115
}

0 commit comments

Comments
 (0)