mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-07-30 16:26:21 +08:00
Merge pull request #398 from redis-performance/exp062-063-combo
Enable the 4-digit SWAR follow-up on GCC + skip the rounding-mode probe for long mantissas
This commit is contained in:
commit
f6df0f2917
@ -268,10 +268,9 @@ loop_parse_if_eight_digits(char const *&p, char const *const pend,
|
|||||||
}
|
}
|
||||||
// Consume a remaining 4-7 digit run in a single SWAR step instead of
|
// Consume a remaining 4-7 digit run in a single SWAR step instead of
|
||||||
// byte-by-byte (reuses the existing 4-digit helpers). The parsed result is
|
// byte-by-byte (reuses the existing 4-digit helpers). The parsed result is
|
||||||
// identical either way. Gated to clang: on gcc the extra 4-digit check
|
// identical either way. Historically gated to clang because gcc regressed on
|
||||||
// regresses inputs whose remainder is shorter than 4 digits (it becomes pure
|
// short remainders, but that verdict predates the span-elision restructure;
|
||||||
// overhead there); clang does not show that.
|
// with the leaner hot path the 4-digit step now wins on gcc as well.
|
||||||
#if defined(__clang__)
|
|
||||||
if ((pend - p) >= 4) {
|
if ((pend - p) >= 4) {
|
||||||
uint32_t const val4 = read4_to_u32(p);
|
uint32_t const val4 = read4_to_u32(p);
|
||||||
if (is_made_of_four_digits_fast(val4)) {
|
if (is_made_of_four_digits_fast(val4)) {
|
||||||
@ -280,7 +279,6 @@ loop_parse_if_eight_digits(char const *&p, char const *const pend,
|
|||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class parse_error {
|
enum class parse_error {
|
||||||
|
|||||||
@ -198,7 +198,14 @@ clinger_fast_path_impl(uint64_t mantissa, int64_t exponent, bool is_negative,
|
|||||||
// We proceed optimistically, assuming that detail::rounds_to_nearest()
|
// We proceed optimistically, assuming that detail::rounds_to_nearest()
|
||||||
// returns true.
|
// returns true.
|
||||||
if (binary_format<T>::min_exponent_fast_path() <= exponent &&
|
if (binary_format<T>::min_exponent_fast_path() <= exponent &&
|
||||||
exponent <= binary_format<T>::max_exponent_fast_path()) {
|
exponent <= binary_format<T>::max_exponent_fast_path() &&
|
||||||
|
mantissa <= binary_format<T>::max_mantissa_fast_path()) {
|
||||||
|
// The mantissa bound above is a necessary condition for BOTH branches
|
||||||
|
// below: the rounding-mode-dependent branch checks the tighter
|
||||||
|
// max_mantissa_fast_path(exponent) <= max_mantissa_fast_path(). Testing
|
||||||
|
// it before detail::rounds_to_nearest() spares long-mantissa inputs
|
||||||
|
// (which can never take the fast path) the volatile-float probe.
|
||||||
|
//
|
||||||
// Unfortunately, the conventional Clinger's fast path is only possible
|
// Unfortunately, the conventional Clinger's fast path is only possible
|
||||||
// when the system rounds to the nearest float.
|
// when the system rounds to the nearest float.
|
||||||
//
|
//
|
||||||
@ -209,18 +216,16 @@ clinger_fast_path_impl(uint64_t mantissa, int64_t exponent, bool is_negative,
|
|||||||
if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
|
if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
|
||||||
// We have that fegetround() == FE_TONEAREST.
|
// We have that fegetround() == FE_TONEAREST.
|
||||||
// Next is Clinger's fast path.
|
// Next is Clinger's fast path.
|
||||||
if (mantissa <= binary_format<T>::max_mantissa_fast_path()) {
|
value = T(mantissa);
|
||||||
value = T(mantissa);
|
if (exponent < 0) {
|
||||||
if (exponent < 0) {
|
value = value / binary_format<T>::exact_power_of_ten(-exponent);
|
||||||
value = value / binary_format<T>::exact_power_of_ten(-exponent);
|
} else {
|
||||||
} else {
|
value = value * binary_format<T>::exact_power_of_ten(exponent);
|
||||||
value = value * binary_format<T>::exact_power_of_ten(exponent);
|
|
||||||
}
|
|
||||||
if (is_negative) {
|
|
||||||
value = -value;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (is_negative) {
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// We do not have that fegetround() == FE_TONEAREST.
|
// We do not have that fegetround() == FE_TONEAREST.
|
||||||
// Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
|
// Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user