atrosinenko created this revision.
atrosinenko added reviewers: scanon, koviankevin, MaskRay, howard.hinnant.
Herald added subscribers: Sanitizers, dberris.
Herald added a project: Sanitizers.
atrosinenko requested review of this revision.

This patch eliminates some other UB in a slightly more tricky way than D86299: 
[compiler-rt][builtins] Factor out some common bit manipulations 
<https://reviews.llvm.org/D86299>.

- Introduce a `SIGN_OF(signed_int)` macro (not UB-related, just to give this 
trick a descriptive name)
- Make the "negate if sign is -1" trick operate on corresponding **unsigned** 
types. Not factoring it out due to the "interface" of that macro would probably 
be quite error-prone.

This patch is expected to be NFC except for eliminating some UB identified by 
unit tests.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D86414

Files:
  compiler-rt/lib/builtins/absvdi2.c
  compiler-rt/lib/builtins/absvsi2.c
  compiler-rt/lib/builtins/absvti2.c
  compiler-rt/lib/builtins/floattidf.c
  compiler-rt/lib/builtins/floattixf.c
  compiler-rt/lib/builtins/int_div_impl.inc
  compiler-rt/lib/builtins/int_types.h

Index: compiler-rt/lib/builtins/int_types.h
===================================================================
--- compiler-rt/lib/builtins/int_types.h
+++ 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;
Index: compiler-rt/lib/builtins/int_div_impl.inc
===================================================================
--- compiler-rt/lib/builtins/int_div_impl.inc
+++ 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
Index: compiler-rt/lib/builtins/floattixf.c
===================================================================
--- compiler-rt/lib/builtins/floattixf.c
+++ 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) {
Index: compiler-rt/lib/builtins/floattidf.c
===================================================================
--- compiler-rt/lib/builtins/floattidf.c
+++ 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) {
Index: compiler-rt/lib/builtins/absvti2.c
===================================================================
--- compiler-rt/lib/builtins/absvti2.c
+++ 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
Index: compiler-rt/lib/builtins/absvsi2.c
===================================================================
--- compiler-rt/lib/builtins/absvsi2.c
+++ 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;
 }
Index: compiler-rt/lib/builtins/absvdi2.c
===================================================================
--- compiler-rt/lib/builtins/absvdi2.c
+++ 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;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D86414: [compil... Anatoly Trosinenko via Phabricator via cfe-commits

Reply via email to