diff --git a/compiler-rt/lib/builtins/absvdi2.c b/compiler-rt/lib/builtins/absvdi2.c --- a/compiler-rt/lib/builtins/absvdi2.c +++ b/compiler-rt/lib/builtins/absvdi2.c @@ -17,9 +17,8 @@ // Effects: aborts if abs(x) < 0 COMPILER_RT_ABI di_int __absvdi2(di_int a) { - const int N = (int)(sizeof(di_int) * CHAR_BIT); - if (a == ((di_int)1 << (N - 1))) + if (a == MIN_SIGNED(di_int)) compilerrt_abort(); - const di_int t = a >> (N - 1); - return (a ^ t) - t; + const di_int t = SIGN_OF(a); + return (du_int)(a ^ t) - (du_int)t; } diff --git a/compiler-rt/lib/builtins/absvsi2.c b/compiler-rt/lib/builtins/absvsi2.c --- a/compiler-rt/lib/builtins/absvsi2.c +++ b/compiler-rt/lib/builtins/absvsi2.c @@ -17,9 +17,8 @@ // Effects: aborts if abs(x) < 0 COMPILER_RT_ABI si_int __absvsi2(si_int a) { - const int N = (int)(sizeof(si_int) * CHAR_BIT); - if (a == ((si_int)1 << (N - 1))) + if (a == MIN_SIGNED(si_int)) compilerrt_abort(); - const si_int t = a >> (N - 1); - return (a ^ t) - t; + const si_int t = SIGN_OF(a); + return (su_int)(a ^ t) - (su_int)t; } diff --git a/compiler-rt/lib/builtins/absvti2.c b/compiler-rt/lib/builtins/absvti2.c --- a/compiler-rt/lib/builtins/absvti2.c +++ b/compiler-rt/lib/builtins/absvti2.c @@ -19,11 +19,10 @@ // Effects: aborts if abs(x) < 0 COMPILER_RT_ABI ti_int __absvti2(ti_int a) { - const int N = (int)(sizeof(ti_int) * CHAR_BIT); - if (a == ((ti_int)1 << (N - 1))) + if (a == MIN_SIGNED(ti_int)) compilerrt_abort(); - const ti_int s = a >> (N - 1); - return (a ^ s) - s; + const ti_int t = SIGN_OF(a); + return (tu_int)(a ^ t) - (tu_int)t; } #endif // CRT_HAS_128BIT diff --git a/compiler-rt/lib/builtins/floattidf.c b/compiler-rt/lib/builtins/floattidf.c --- a/compiler-rt/lib/builtins/floattidf.c +++ b/compiler-rt/lib/builtins/floattidf.c @@ -25,9 +25,9 @@ COMPILER_RT_ABI double __floattidf(ti_int a) { if (a == 0) return 0.0; - const unsigned N = sizeof(ti_int) * CHAR_BIT; - const ti_int s = a >> (N - 1); - a = (a ^ s) - s; + const unsigned N = bitsizeof(ti_int); + const ti_int s = SIGN_OF(a); + a = (tu_int)(a ^ s) - (tu_int)s; int sd = N - __clzti2(a); // number of significant digits int e = sd - 1; // exponent if (sd > DBL_MANT_DIG) { diff --git a/compiler-rt/lib/builtins/floattixf.c b/compiler-rt/lib/builtins/floattixf.c --- a/compiler-rt/lib/builtins/floattixf.c +++ b/compiler-rt/lib/builtins/floattixf.c @@ -26,9 +26,9 @@ COMPILER_RT_ABI long double __floattixf(ti_int a) { if (a == 0) return 0.0; - const unsigned N = sizeof(ti_int) * CHAR_BIT; - const ti_int s = a >> (N - 1); - a = (a ^ s) - s; + const unsigned N = bitsizeof(ti_int); + const ti_int s = SIGN_OF(a); + a = (tu_int)(a ^ s) - (tu_int)s; int sd = N - __clzti2(a); // number of significant digits int e = sd - 1; // exponent if (sd > LDBL_MANT_DIG) { diff --git a/compiler-rt/lib/builtins/int_div_impl.inc b/compiler-rt/lib/builtins/int_div_impl.inc --- a/compiler-rt/lib/builtins/int_div_impl.inc +++ b/compiler-rt/lib/builtins/int_div_impl.inc @@ -71,25 +71,31 @@ #ifdef COMPUTE_UDIV static __inline fixint_t __divXi3(fixint_t a, fixint_t b) { - const int N = (int)(sizeof(fixint_t) * CHAR_BIT) - 1; - fixint_t s_a = a >> N; // s_a = a < 0 ? -1 : 0 - fixint_t s_b = b >> N; // s_b = b < 0 ? -1 : 0 - a = (a ^ s_a) - s_a; // negate if s_a == -1 - b = (b ^ s_b) - s_b; // negate if s_b == -1 - s_a ^= s_b; // sign of quotient - return (COMPUTE_UDIV(a, b) ^ s_a) - s_a; // negate if s_a == -1 + // extract signs (0 or -1) of arguments + fixint_t s_a = SIGN_OF(a); + fixint_t s_b = SIGN_OF(b); + // compute absolute values of arguments + a = (fixuint_t)(a ^ s_a) - (fixuint_t)s_a; + b = (fixuint_t)(b ^ s_b) - (fixuint_t)s_b; + // compute a sign of quotient + s_a ^= s_b; + // compute an absolute value of quotient and negate it if needed + return (fixuint_t)(COMPUTE_UDIV(a, b) ^ s_a) - (fixuint_t)s_a; } #endif // COMPUTE_UDIV #ifdef ASSIGN_UMOD static __inline fixint_t __modXi3(fixint_t a, fixint_t b) { - const int N = (int)(sizeof(fixint_t) * CHAR_BIT) - 1; - fixint_t s = b >> N; // s = b < 0 ? -1 : 0 - b = (b ^ s) - s; // negate if s == -1 - s = a >> N; // s = a < 0 ? -1 : 0 - a = (a ^ s) - s; // negate if s == -1 + // compute an absolute value of b + fixint_t s = SIGN_OF(b); + b = (fixuint_t)(b ^ s) - (fixuint_t)s; + // compute an absolute value of a + s = SIGN_OF(a); + a = (fixuint_t)(a ^ s) - (fixuint_t)s; + // compute an absolute value of the result fixuint_t res; ASSIGN_UMOD(res, a, b); - return (res ^ s) - s; // negate if s == -1 + // make the result have the same sign as b + return (fixuint_t)(res ^ s) - (fixuint_t)s; } #endif // ASSIGN_UMOD diff --git a/compiler-rt/lib/builtins/int_types.h b/compiler-rt/lib/builtins/int_types.h --- a/compiler-rt/lib/builtins/int_types.h +++ b/compiler-rt/lib/builtins/int_types.h @@ -60,6 +60,7 @@ #define MIN_SIGNED(type) ((AS_SIGNED(type))SIGN_BIT(type)) #define MAX_SIGNED(type) ((AS_SIGNED(type))(SIGN_BIT(type) - 1U)) #define MAX_UNSIGNED(type) (~(AS_UNSIGNED(type))0)) +#define SIGN_OF(signed_int) ((signed_int) >> (bitsizeof(signed_int) - 1)) typedef union { di_int all;