1
0
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:
Niels Dossche
2024-05-07 18:24:00 +02:00
committed by GitHub
parent 304f19b139
commit 90a5b871ef
4 changed files with 12 additions and 27 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}
}