Changeset: 003e2634d3bf for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/003e2634d3bf
Modified Files:
        gdk/gdk_aggr.c
        gdk/gdk_calc_private.h
        gdk/gdk_join.c
Branch: nilmask
Log Message:

Checkpoint: use builtins to check for unsigned overflow.


diffs (truncated from 364 to 300 lines):

diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -440,9 +440,9 @@ dofsum(const void *restrict values, oid 
                                TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) { \
                                        x = vals[ci->seq + i - seqb];   \
                                        ADDI_WITH_CHECK(x, sum,         \
-                                                      TYPE2, sum,      \
-                                                      GDK_##TYPE2##_max, \
-                                                      goto overflow);  \
+                                                       TYPE2, sum,     \
+                                                       GDK_##TYPE2##_max, \
+                                                       goto overflow); \
                                }                                       \
                                TIMEOUT_CHECK(qry_ctx,                  \
                                              
GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
@@ -458,9 +458,9 @@ dofsum(const void *restrict values, oid 
                                                }                       \
                                        } else {                        \
                                                ADDI_WITH_CHECK(x, sum, \
-                                                              TYPE2, sum, \
-                                                              
GDK_##TYPE2##_max, \
-                                                              goto overflow); \
+                                                               TYPE2, sum, \
+                                                               
GDK_##TYPE2##_max, \
+                                                               goto overflow); 
\
                                                seenval = true;         \
                                        }                               \
                                }                                       \
@@ -486,9 +486,9 @@ dofsum(const void *restrict values, oid 
                                        }                               \
                                } else {                                \
                                        ADDI_WITH_CHECK(x, sum,         \
-                                                      TYPE2, sum,      \
-                                                      GDK_##TYPE2##_max, \
-                                                      goto overflow);  \
+                                                       TYPE2, sum,     \
+                                                       GDK_##TYPE2##_max, \
+                                                       goto overflow); \
                                        seenval = true;                 \
                                }                                       \
                        }                                               \
@@ -715,7 +715,7 @@ dofsum(const void *restrict values, oid 
                        sum = 0;                                        \
                        TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {       \
                                x = vals[ci->seq + i - seqb];           \
-                               ADD_WITH_CHECK(x, sum,                  \
+                               ADDU_WITH_CHECK(x, sum,                 \
                                               TYPE2, sum,              \
                                               GDK_##TYPE2##_max,       \
                                               goto overflow);          \
@@ -730,10 +730,10 @@ dofsum(const void *restrict values, oid 
                        sum = 0;                                        \
                        TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {       \
                                x = vals[canditer_next(ci) - seqb];     \
-                               ADD_WITH_CHECK(x, sum,                  \
-                                              TYPE2, sum,              \
-                                              GDK_##TYPE2##_max,       \
-                                              goto overflow);          \
+                               ADDU_WITH_CHECK(x, sum,                 \
+                                               TYPE2, sum,             \
+                                               GDK_##TYPE2##_max,      \
+                                               goto overflow);         \
                        }                                               \
                        TIMEOUT_CHECK(qry_ctx,                          \
                                      GOTO_LABEL_TIMEOUT_HANDLER(bailout, 
qry_ctx)); \
@@ -746,7 +746,7 @@ dofsum(const void *restrict values, oid 
                                    (gids[i] >= min && gids[i] <= max)) { \
                                        gid = gids ? gids[i] - min : (oid) i; \
                                        x = vals[ci->seq + i - seqb];   \
-                                       ADD_WITH_CHECK(                 \
+                                       ADDU_WITH_CHECK(                \
                                                x,                      \
                                                sums[gid],              \
                                                TYPE2,                  \
@@ -766,7 +766,7 @@ dofsum(const void *restrict values, oid 
                                    (gids[i] >= min && gids[i] <= max)) { \
                                        gid = gids ? gids[i] - min : (oid) i; \
                                        x = vals[i];                    \
-                                       ADD_WITH_CHECK(                 \
+                                       ADDU_WITH_CHECK(                \
                                                x,                      \
                                                sums[gid],              \
                                                TYPE2,                  \
@@ -1560,7 +1560,7 @@ BATsum(void *res, int tp, BAT *b, BAT *s
                                        else                            \
                                                gid = (oid) i;          \
                                }                                       \
-                               MUL4_WITH_CHECK(                        \
+                               MULU4_WITH_CHECK(                       \
                                        vals[i],                        \
                                        prods[gid],                     \
                                        TYPE2, prods[gid],              \
@@ -3895,9 +3895,9 @@ BATgroupavg3combine(BAT *avg, BAT *rem, 
                        if (is_##TYPE##_nil(x))                         \
                                continue;                               \
                        ADDI_WITH_CHECK(x, sum,                         \
-                                      lng_hge, sum,                    \
-                                      GDK_##lng_hge##_max,             \
-                                      goto overflow##TYPE);            \
+                                       lng_hge, sum,                   \
+                                       GDK_##lng_hge##_max,            \
+                                       goto overflow##TYPE);           \
                        /* don't count value until after overflow check */ \
                        n++;                                            \
                }                                                       \
@@ -3951,10 +3951,10 @@ BATgroupavg3combine(BAT *avg, BAT *rem, 
                TIMEOUT_LOOP(ci.ncand, qry_ctx) {                       \
                        i = canditer_next(&ci) - b->hseqbase;           \
                        x = ((const TYPE *) src)[i];                    \
-                       ADD_WITH_CHECK(x, sum,                          \
-                                      lng_hge, sum,                    \
-                                      GDK_##lng_hge##_max,             \
-                                      goto overflow##TYPE);            \
+                       ADDU_WITH_CHECK(x, sum,                         \
+                                       lng_hge, sum,                   \
+                                       GDK_##lng_hge##_max,            \
+                                       goto overflow##TYPE);           \
                        /* don't count value until after overflow check */ \
                        n++;                                            \
                }                                                       \
diff --git a/gdk/gdk_calc_private.h b/gdk/gdk_calc_private.h
--- a/gdk/gdk_calc_private.h
+++ b/gdk/gdk_calc_private.h
@@ -44,6 +44,12 @@
                        on_overflow;                                    \
                }                                                       \
        } while (0)
+#define UOP_WITH_CHECK(lft, rgt, dst, op, max, on_overflow)            \
+       do {                                                            \
+               if (__builtin_##op##_overflow(lft, rgt, &(dst))) {      \
+                       on_overflow;                                    \
+               }                                                       \
+       } while (0)
 #endif
 #endif
 
@@ -71,11 +77,21 @@
 /* integer version using Gnu CC builtin function for overflow check */
 #define ADDI_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)                
\
        OP_WITH_CHECK(lft, rgt, dst, add, max, on_overflow)
+#define ADDU_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)                
\
+       UOP_WITH_CHECK(lft, rgt, dst, add, max, on_overflow)
 #else
 /* integer version using generic version */
 #define ADDI_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow) \
        ADD_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)
-#endif /* HAVE___BUILTIN_ADD_OVERFLOW */
+#define ADDU_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow) \
+       do {                                                    \
+               if ((max) - (rgt) < (lft)) {                    \
+                       on_overflow;                            \
+               } else {                                        \
+                       (dst) = (TYPE3) (lft) + (rgt);          \
+               }                                               \
+       } while (0)
+#endif
 
 /* floating point version using generic version */
 #define ADDF_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow) \
@@ -105,11 +121,21 @@
 /* integer version using Gnu CC builtin function for overflow check */
 #define SUBI_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)                
\
        OP_WITH_CHECK(lft, rgt, dst, sub, max, on_overflow)
+#define SUBU_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)                
\
+       UOP_WITH_CHECK(lft, rgt, dst, sub, max, on_overflow)
 #else
 /* integer version using generic version */
 #define SUBI_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow) \
        SUB_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)
-#endif /* HAVE___BUILTIN_ADD_OVERFLOW */
+#define SUBU_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow)        \
+       do {                                                    \
+               if ((rgt) > (lft)) {                            \
+                       on_overflow;                            \
+               } else {                                        \
+                       (dst) = (TYPE3) (lft) - (rgt);          \
+               }                                               \
+       } while (0)
+#endif
 
 /* floating point version using generic version */
 #define SUBF_WITH_CHECK(lft, rgt, TYPE3, dst, max, on_overflow) \
@@ -132,21 +158,37 @@
 /* integer version using Gnu CC builtin function for overflow check */
 #define MULI4_WITH_CHECK(lft, rgt, TYPE3, dst, max, TYPE4, on_overflow) \
        OP_WITH_CHECK(lft, rgt, dst, mul, max, on_overflow)
+#define MULU4_WITH_CHECK(lft, rgt, TYPE3, dst, max, TYPE4, on_overflow) \
+       OP_WITH_CHECK(lft, rgt, dst, mul, max, on_overflow)
 #define LNGMUL_CHECK(lft, rgt, dst, max, on_overflow)                  \
        OP_WITH_CHECK(lft, rgt, dst, mul, max, on_overflow)
 #else
 /* integer version using generic version */
 #define MULI4_WITH_CHECK(lft, rgt, TYPE3, dst, max, TYPE4, on_overflow) \
        MUL4_WITH_CHECK(lft, rgt, TYPE3, dst, max, TYPE4, on_overflow)
+#define MULU4_WITH_CHECK(lft, rgt, TYPE3, dst, max, TYPE4, on_overflow)        
\
+       do {                                                            \
+               TYPE4 c = (TYPE4) (lft) * (rgt);                        \
+               if (c > (TYPE4) (max)) {                                \
+                       on_overflow;                                    \
+               } else {                                                \
+                       (dst) = (TYPE3) c;                              \
+               }                                                       \
+       } while (0)
 #ifdef HAVE_HGE
 #define LNGMUL_CHECK(lft, rgt, dst, max, on_overflow)                  \
        MULI4_WITH_CHECK(lft, rgt, lng, dst, max, hge, on_overflow)
+#define LNGMULU_CHECK(lft, rgt, dst, max, on_overflow)                 \
+       MULU4_WITH_CHECK(lft, rgt, lng, dst, max, hge, on_overflow)
 #elif defined(HAVE___INT128)
 #define LNGMUL_CHECK(lft, rgt, dst, max, on_overflow)                  \
        MULI4_WITH_CHECK(lft, rgt, lng, dst, max, __int128, on_overflow)
+#define LNGMULU_CHECK(lft, rgt, dst, max, on_overflow)                 \
+       MULU4_WITH_CHECK(lft, rgt, lng, dst, max, hge, on_overflow)
 #elif defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
 #include <intrin.h>
 #pragma intrinsic(_mul128)
+#pragma intrinsic(_umul128)
 #define LNGMUL_CHECK(lft, rgt, dst, max, on_overflow)                  \
        do {                                                            \
                __int64 clo, chi;                                       \
@@ -158,6 +200,16 @@
                        on_overflow;                                    \
                }                                                       \
        } while (0)
+#define LNGMULU_CHECK(lft, rgt, dst, max, on_overflow)                 \
+       do {                                                            \
+               unsigned __int64 clo, chi;                              \
+               clo = _umul128((unsigned __int64) (lft), (unsigned __int64) 
(rgt), &chi);       \
+               if (chi == 0 /*&& clo <= (max)*/) {                     \
+                       (dst) = (ulng) clo;                             \
+               } else {                                                \
+                       on_overflow;                                    \
+               }                                                       \
+       } while (0)
 #else
 #define LNGMUL_CHECK(lft, rgt, dst, max, on_overflow)                  \
        do {                                                            \
@@ -188,6 +240,26 @@
                        on_overflow;                                    \
                }                                                       \
        } while (0)
+#define LNGMULU_CHECK(lft, rgt, dst, max, on_overflow)                 \
+       do {                                                            \
+               ulng a = (lft), b = (rgt);                              \
+               unsigned int a1, a2, b1, b2;                            \
+               ulng c;                                                 \
+                                                                       \
+               a1 = (unsigned int) (a >> 32);                          \
+               a2 = (unsigned int) a;                                  \
+               b1 = (unsigned int) (b >> 32);                          \
+               b2 = (unsigned int) b;                                  \
+               /* result = (a1*b1<<64) + (a1*b2+a2*b1<<32) + a2*b2 */  \
+               if ((a1 == 0 || b1 == 0) &&                             \
+                   ((c = (ulng) a1 * b2 + (ulng) a2 * b1) & (~(ulng)0 << 31)) 
== 0 && \
+                   (((c = (c << 32) + (ulng) a2 * b2) & ((ulng) 1 << 63)) == 0 
&& \
+                    (c) <= (ulng) (max))) {                            \
+                       (dst) = (ulng) c;                               \
+               } else {                                                \
+                       on_overflow;                                    \
+               }                                                       \
+       } while (0)
 #endif /* HAVE_HGE */
 #endif
 #define MULF4_WITH_CHECK(lft, rgt, TYPE3, dst, max, TYPE4, on_overflow) \
@@ -227,7 +299,7 @@
                        on_overflow;                                    \
                }                                                       \
        } while (0)
-#endif /* HAVE___BUILTIN_ADD_OVERFLOW */
+#endif
 #endif /* HAVE_HGE */
 
 #define AVERAGE_ITER(TYPE, x, a, r, n)                                 \
diff --git a/gdk/gdk_join.c b/gdk/gdk_join.c
--- a/gdk/gdk_join.c
+++ b/gdk/gdk_join.c
@@ -4872,19 +4872,19 @@ BATbandjoin(BAT **r1p, BAT **r2p, BAT *l
                                        continue;
                                lng v1, v2;
                                SUBI_WITH_CHECK(*(const lng *)vr,
-                                              *(const lng *)c1,
-                                              lng, v1,
-                                              GDK_lng_max,
-                                              do{if(*(const lng*)c1<0)goto 
nolmatch;else goto lmatch1;}while(false));
+                                               *(const lng *)c1,
+                                               lng, v1,
+                                               GDK_lng_max,
+                                               do{if(*(const lng*)c1<0)goto 
nolmatch;else goto lmatch1;}while(false));
                                if (*(const lng *)vl <= v1 &&
                                    (!linc || *(const lng *)vl != v1))
                                        continue;
                                  lmatch1:
-                               ADDI_WITH_CHECK(*(const lng *)vr,
-                                              *(const lng *)c2,
-                                              lng, v2,
-                                              GDK_lng_max,
-                                              do{if(*(const lng*)c2>0)goto 
nolmatch;else goto lmatch2;}while(false));
+                                ADDI_WITH_CHECK(*(const lng *)vr,
+                                                *(const lng *)c2,
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to