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