Skip to content

Commit 33907c5

Browse files
committed
math: Shorten the ASR implementation
Thanks to Per Vognsen for an implementation which both gcc and clang appear to reduce to a single asr instruction. Signed-off-by: Keith Packard <keithp@keithp.com>
1 parent e1110be commit 33907c5

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

newlib/libm/common/fdlibm.h

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -338,32 +338,33 @@ __undefined_shift_size(int x, int s);
338338
#if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer)
339339

340340
/*
341-
* Compute arithmetic right shift the hard way -- logical shift and
342-
* then shift the sign bit and negate it to replicate it
341+
* Compute arithmetic right shift. For negative values, flip the bits,
342+
* shift and flip back. Otherwise, just shift. Thanks to Per Vognsen
343+
* for this version which both gcc and clang both currently optimize
344+
* to a single asr instruction in small tests.
343345
*/
344-
#define __asr(t, n) \
345-
static inline t \
346-
__asr_ ## n(t x, int s) { \
347-
return (t) ((unsigned t) x >> s) | \
348-
-(((unsigned t) x & ((unsigned t) 1 << (8 * sizeof(t) - 1))) >> s); \
349-
} \
350-
351-
__asr(char, char)
346+
#define __asr(t, n) \
347+
static inline t \
348+
__asr_ ## n(t x, int s) { \
349+
return x < 0 ? ~(~x >> s) : x >> s; \
350+
} \
351+
352+
__asr(signed char, signed_char)
352353
__asr(short, short)
353354
__asr(int, int)
354355
__asr(long, long)
355356
__asr(long long, long_long)
356357

357-
#define asr(__x,__s) ((sizeof(__x) == sizeof(char)) ? \
358-
(__typeof(__x))__asr_char(__x, __s) : \
359-
(sizeof(__x) == sizeof(short)) ? \
360-
(__typeof(__x))__asr_short(__x, __s) : \
361-
(sizeof(__x) == sizeof(int)) ? \
362-
(__typeof(__x))__asr_int(__x, __s) : \
363-
(sizeof(__x) == sizeof(long)) ? \
364-
(__typeof(__x))__asr_long(__x, __s) : \
365-
(sizeof(__x) == sizeof(long long)) ? \
366-
(__typeof(__x))__asr_long_long(__x, __s): \
358+
#define asr(__x,__s) ((sizeof(__x) == sizeof(char)) ? \
359+
(__typeof(__x))__asr_signed_char(__x, __s) : \
360+
(sizeof(__x) == sizeof(short)) ? \
361+
(__typeof(__x))__asr_short(__x, __s) : \
362+
(sizeof(__x) == sizeof(int)) ? \
363+
(__typeof(__x))__asr_int(__x, __s) : \
364+
(sizeof(__x) == sizeof(long)) ? \
365+
(__typeof(__x))__asr_long(__x, __s) : \
366+
(sizeof(__x) == sizeof(long long)) ? \
367+
(__typeof(__x))__asr_long_long(__x, __s): \
367368
__undefined_shift_size(__x, __s))
368369
#else
369370
#define asr(__x, __s) ((__x) >> (__s))

0 commit comments

Comments
 (0)