[前][次][番号順一覧][スレッド一覧]

ruby-changes:45711

From: shyouhei <ko1@a...>
Date: Mon, 6 Mar 2017 15:04:58 +0900 (JST)
Subject: [ruby-changes:45711] shyouhei:r57784 (trunk): use HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW

shyouhei	2017-03-06 15:04:52 +0900 (Mon, 06 Mar 2017)

  New Revision: 57784

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=57784

  Log:
    use HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
    
    We already check for __builtin_mul_overflow in configure but never
    actually referred it before.  Why not call it if available, because
    that should render supposedly-optimial assembly outputs.
    
    Optionally if __builtin_mul_overflow_p is available, which is the case
    for recent GCC, use that to detect fixnum overflow.  This is much
    faster than the previous.  On my machine generated assembly of
    numeric.c:int_pow reduces from 480 to 448 bytes, according to nm(1).
    Also on my machine, following script boosts from 7.819 to 6.929 sec.
    
    time ./miniruby -e 'i=0; while i < 30_000_000 do i += 1; 7 ** 23; end'
    
    Signed-off-by: Urabe, Shyouhei <shyouhei@r...>

  Modified files:
    trunk/configure.in
    trunk/internal.h
    trunk/process.c
Index: configure.in
===================================================================
--- configure.in	(revision 57783)
+++ configure.in	(revision 57784)
@@ -2528,6 +2528,7 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_ctzll, https://github.com/ruby/ruby/blob/trunk/configure.in#L2528
 RUBY_CHECK_BUILTIN_FUNC(__builtin_add_overflow, [int x;__builtin_add_overflow(0,0,&x)])
 RUBY_CHECK_BUILTIN_FUNC(__builtin_sub_overflow, [int x;__builtin_sub_overflow(0,0,&x)])
 RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow, [int x;__builtin_mul_overflow(0,0,&x)])
+RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow_p, [__builtin_mul_overflow_p(0,0,(int)0)])
 RUBY_CHECK_BUILTIN_FUNC(__builtin_constant_p, [__builtin_constant_p(0)])
 RUBY_CHECK_BUILTIN_FUNC(__builtin_choose_expr, [
     [int x[__extension__(__builtin_choose_expr(1, 1, -1))]];
Index: internal.h
===================================================================
--- internal.h	(revision 57783)
+++ internal.h	(revision 57784)
@@ -96,15 +96,41 @@ extern "C" { https://github.com/ruby/ruby/blob/trunk/internal.h#L96
 #endif
 #define TIMET_MAX_PLUS_ONE (2*(double)(TIMET_MAX/2+1))
 
+#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P
+#define MUL_OVERFLOW_P(a, b) \
+    __builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif defined HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
+#define MUL_OVERFLOW_P(a, b) \
+    ({__typeof__(a) c; __builtin_mul_overflow((a), (b), &c);})
+#endif
+
 #define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
     (a) == 0 ? 0 : \
     (a) == -1 ? (b) < -(max) : \
     (a) > 0 ? \
       ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
       ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
+
+#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P
+/* __builtin_mul_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+#define MUL_OVERFLOW_FIXNUM_P(a, b) ({ \
+    struct { SIGNED_VALUE fixnum : SIZEOF_VALUE * CHAR_BIT - 1; } c; \
+    __builtin_mul_overflow_p((a), (b), c.fixnum); \
+})
+#else
 #define MUL_OVERFLOW_FIXNUM_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
-#define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
-#define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+
+#ifdef MUL_OVERFLOW_P
+#define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
+#define MUL_OVERFLOW_LONG_P(a, b)      MUL_OVERFLOW_P(a, b)
+#define MUL_OVERFLOW_INT_P(a, b)       MUL_OVERFLOW_P(a, b)
+#else
+#define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_LONG_MIN, LONG_LONG_MAX)
+#define MUL_OVERFLOW_LONG_P(a, b)      MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+#define MUL_OVERFLOW_INT_P(a, b)       MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
 
 #ifndef swap16
 # ifdef HAVE_BUILTIN___BUILTIN_BSWAP16
Index: process.c
===================================================================
--- process.c	(revision 57783)
+++ process.c	(revision 57784)
@@ -6916,11 +6916,13 @@ typedef LONG_LONG timetick_int_t; https://github.com/ruby/ruby/blob/trunk/process.c#L6916
 #define TIMETICK_INT_MIN LLONG_MIN
 #define TIMETICK_INT_MAX LLONG_MAX
 #define TIMETICK_INT2NUM(v) LL2NUM(v)
+#define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_LONG_P(a, b)
 #else
 typedef long timetick_int_t;
 #define TIMETICK_INT_MIN LONG_MIN
 #define TIMETICK_INT_MAX LONG_MAX
 #define TIMETICK_INT2NUM(v) LONG2NUM(v)
+#define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_P(a, b)
 #endif
 
 CONSTFUNC(static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t));
@@ -7036,8 +7038,7 @@ timetick2integer(struct timetick *ttp, https://github.com/ruby/ruby/blob/trunk/process.c#L7038
         timetick_int_t t = ttp->giga_count * 1000000000 + ttp->count;
         for (i = 0; i < num_numerators; i++) {
             timetick_int_t factor = numerators[i];
-            if (MUL_OVERFLOW_SIGNED_INTEGER_P(factor, t,
-                        TIMETICK_INT_MIN, TIMETICK_INT_MAX))
+            if (MUL_OVERFLOW_TIMETICK_P(factor, t))
                 goto generic;
             t *= factor;
         }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]