mirror of
https://sourceware.org/git/glibc.git
synced 2026-10-24 01:33:52 +03:00
aarch64: Optimise AdvSIMD log1pf
Optimise AdvSIMD log1pf by vectorising the special case and by reducing the range of values passed to the special case. Previously, high values such as 0x1.1p127 where treated as special cases, but now the special cases are for when the input is: Less than or equal to -1 +/- INFINITY +/- NaN Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
committed by
Adhemerval Zanella
parent
762bb01d4e
commit
f42c135157
@@ -20,28 +20,50 @@
|
||||
#include "v_math.h"
|
||||
#include "v_log1pf_inline.h"
|
||||
|
||||
const static struct v_log1pf_data data = V_LOG1PF_CONSTANTS_TABLE;
|
||||
|
||||
static float32x4_t NOINLINE VPCS_ATTR
|
||||
special_case (float32x4_t x, uint32x4_t cmp)
|
||||
static const struct data
|
||||
{
|
||||
return v_call_f32 (log1pf, x, log1pf_inline (x, ptr_barrier (&data)), cmp);
|
||||
struct v_log1pf_data d;
|
||||
float32x4_t nan, pinf, minf;
|
||||
} data = {
|
||||
.d = V_LOG1PF_CONSTANTS_TABLE,
|
||||
.nan = V4 (NAN),
|
||||
.pinf = V4 (INFINITY),
|
||||
.minf = V4 (-INFINITY),
|
||||
};
|
||||
|
||||
static inline float32x4_t
|
||||
special_case (float32x4_t x, uint32x4_t cmp, const struct data *d)
|
||||
{
|
||||
float32x4_t y = log1pf_inline (x, ptr_barrier (&d->d));
|
||||
y = vbslq_f32 (cmp, d->nan, y);
|
||||
uint32x4_t ret_pinf = vceqq_f32 (x, d->pinf);
|
||||
uint32x4_t ret_minf = vceqq_f32 (x, v_f32 (-1.0));
|
||||
|
||||
y = vbslq_f32 (ret_pinf, d->pinf, y);
|
||||
return vbslq_f32 (ret_minf, d->minf, y);
|
||||
}
|
||||
|
||||
/* Vector log1pf approximation using polynomial on reduced interval. Worst-case
|
||||
error is 1.63 ULP:
|
||||
_ZGVnN4v_log1pf(0x1.216d12p-2) got 0x1.fdcb12p-3
|
||||
want 0x1.fdcb16p-3. */
|
||||
/* Single-precision implementation of vector log1pf(x).
|
||||
Maximum observed error: 1.20 + 0.5
|
||||
_ZGVnN4v_log1pf(0x1.04418ap-2) got 0x1.cfcbd8p-3
|
||||
want 0x1.cfcbdcp-3. */
|
||||
float32x4_t VPCS_ATTR NOINLINE V_NAME_F1 (log1p) (float32x4_t x)
|
||||
{
|
||||
uint32x4_t special_cases = vornq_u32 (vcleq_f32 (x, v_f32 (-1)),
|
||||
vcaleq_f32 (x, v_f32 (0x1p127f)));
|
||||
const struct data *d = ptr_barrier (&data);
|
||||
|
||||
if (__glibc_unlikely (v_any_u32 (special_cases)))
|
||||
return special_case (x, special_cases);
|
||||
/* Use signed integers here to ensure that negative numbers between 0 and -1
|
||||
don't make this expression true. */
|
||||
uint32x4_t is_infnan
|
||||
= vcgeq_s32 (vreinterpretq_s32_f32 (x), vreinterpretq_s32_f32 (d->pinf));
|
||||
/* The OR-NOT is needed to catch -NaN. */
|
||||
uint32x4_t special = vornq_u32 (is_infnan, vcgtq_f32 (x, v_f32 (-1)));
|
||||
|
||||
return log1pf_inline (x, ptr_barrier (&data));
|
||||
if (__glibc_unlikely (v_any_u32 (special)))
|
||||
return special_case (x, special, d);
|
||||
|
||||
return log1pf_inline (x, &d->d);
|
||||
}
|
||||
|
||||
libmvec_hidden_def (V_NAME_F1 (log1p))
|
||||
HALF_WIDTH_ALIAS_F1 (log1p)
|
||||
strong_alias (V_NAME_F1 (log1p), V_NAME_F1 (logp1))
|
||||
|
||||
Reference in New Issue
Block a user