@@ -338,32 +338,33 @@ __undefined_shift_size(int x, int s);
338
338
#if defined(__has_feature ) && __has_feature (undefined_behavior_sanitizer )
339
339
340
340
/*
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.
343
345
*/
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 )
352
353
__asr (short , short )
353
354
__asr (int , int )
354
355
__asr (long , long )
355
356
__asr (long long , long_long )
356
357
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 ): \
367
368
__undefined_shift_size (__x , __s ))
368
369
#else
369
370
#define asr (__x , __s ) ((__x ) >> (__s ))
0 commit comments