mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Simplify conversion in BCMath (#14157)
This simplifies the code, and also might indirectly improve performance due to a decrease in instruction cache pressure. Although the latter is probably negligible. This works because 0x30 has no overlapping bits with [0, 9].
This commit is contained in:
@@ -21,20 +21,16 @@
|
||||
# include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
static char *bc_copy_and_shift_numbers(char *restrict dest, const char *source, const char *source_end, unsigned char shift, bool add)
|
||||
char *bc_copy_and_toggle_bcd(char *restrict dest, const char *source, const char *source_end)
|
||||
{
|
||||
size_t bulk_shift = SWAR_REPEAT(shift);
|
||||
if (!add) {
|
||||
bulk_shift = -bulk_shift;
|
||||
shift = -shift;
|
||||
}
|
||||
const size_t bulk_shift = SWAR_REPEAT('0');
|
||||
|
||||
#ifdef __SSE2__
|
||||
/* SIMD SSE2 bulk shift + copy */
|
||||
__m128i shift_vector = _mm_set1_epi8(shift);
|
||||
__m128i shift_vector = _mm_set1_epi8('0');
|
||||
while (source + sizeof(__m128i) <= source_end) {
|
||||
__m128i bytes = _mm_loadu_si128((const __m128i *) source);
|
||||
bytes = _mm_add_epi8(bytes, shift_vector);
|
||||
bytes = _mm_xor_si128(bytes, shift_vector);
|
||||
_mm_storeu_si128((__m128i *) dest, bytes);
|
||||
|
||||
source += sizeof(__m128i);
|
||||
@@ -50,7 +46,7 @@ static char *bc_copy_and_shift_numbers(char *restrict dest, const char *source,
|
||||
size_t bytes;
|
||||
memcpy(&bytes, source, sizeof(bytes));
|
||||
|
||||
bytes += bulk_shift;
|
||||
bytes ^= bulk_shift;
|
||||
memcpy(dest, &bytes, sizeof(bytes));
|
||||
|
||||
source += sizeof(size_t);
|
||||
@@ -58,20 +54,10 @@ static char *bc_copy_and_shift_numbers(char *restrict dest, const char *source,
|
||||
}
|
||||
|
||||
while (source < source_end) {
|
||||
*dest = *source + shift;
|
||||
*dest = *source ^ '0';
|
||||
dest++;
|
||||
source++;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *bc_copy_ch_val(char *restrict dest, const char *source, const char *source_end)
|
||||
{
|
||||
return bc_copy_and_shift_numbers(dest, source, source_end, '0', false);
|
||||
}
|
||||
|
||||
char *bc_copy_bcd_val(char *restrict dest, const char *source, const char *source_end)
|
||||
{
|
||||
return bc_copy_and_shift_numbers(dest, source, source_end, '0', true);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#ifndef BCMATH_CONVERT_H
|
||||
#define BCMATH_CONVERT_H
|
||||
|
||||
char *bc_copy_ch_val(char *restrict dest, const char *source, const char *source_end);
|
||||
char *bc_copy_bcd_val(char *restrict dest, const char *source, const char *source_end);
|
||||
char *bc_copy_and_toggle_bcd(char *restrict dest, const char *source, const char *source_end);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,13 +57,13 @@ zend_string *bc_num2str_ex(bc_num num, size_t scale)
|
||||
|
||||
/* Load the whole number. */
|
||||
const char *nptr = num->n_value;
|
||||
sptr = bc_copy_bcd_val(sptr, nptr, nptr + num->n_len);
|
||||
sptr = bc_copy_and_toggle_bcd(sptr, nptr, nptr + num->n_len);
|
||||
nptr += num->n_len;
|
||||
|
||||
/* Now the fraction. */
|
||||
if (scale > 0) {
|
||||
*sptr++ = '.';
|
||||
sptr = bc_copy_bcd_val(sptr, nptr, nptr + min_scale);
|
||||
sptr = bc_copy_and_toggle_bcd(sptr, nptr, nptr + min_scale);
|
||||
for (index = num->n_scale; index < scale; index++) {
|
||||
*sptr++ = BCD_CHAR(0);
|
||||
}
|
||||
|
||||
@@ -165,12 +165,12 @@ after_fractional:
|
||||
* If zero_int is true and the str_scale is 0, there is an early return,
|
||||
* so here str_scale is always greater than 0.
|
||||
*/
|
||||
nptr = bc_copy_ch_val(nptr, fractional_ptr, fractional_end);
|
||||
nptr = bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end);
|
||||
} else {
|
||||
const char *integer_end = integer_ptr + digits;
|
||||
nptr = bc_copy_ch_val(nptr, integer_ptr, integer_end);
|
||||
nptr = bc_copy_and_toggle_bcd(nptr, integer_ptr, integer_end);
|
||||
if (str_scale > 0) {
|
||||
nptr = bc_copy_ch_val(nptr, fractional_ptr, fractional_end);
|
||||
nptr = bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user