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

ruby-changes:45716

From: shyouhei <ko1@a...>
Date: Mon, 6 Mar 2017 20:14:12 +0900 (JST)
Subject: [ruby-changes:45716] shyouhei:r57789 (trunk): optimize FIXABLE macro

shyouhei	2017-03-06 20:14:05 +0900 (Mon, 06 Mar 2017)

  New Revision: 57789

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

  Log:
    optimize FIXABLE macro
    
    Looking at the source code, FIXABLE tends to be just before LOING2FIX
    to check applicability of that operation.  Why not try computing first
    then check for overflow, which should be optimial.
    
    I also tried the same thing for unsigned types but resulted in slower
    execution.  It seems RB_POSFIXABLE() is fast enough on modern CPUs.

  Modified files:
    trunk/bignum.c
    trunk/compile.c
    trunk/include/ruby/ruby.h
    trunk/insns.def
    trunk/internal.h
    trunk/numeric.c
    trunk/object.c
    trunk/sprintf.c
Index: sprintf.c
===================================================================
--- sprintf.c	(revision 57788)
+++ sprintf.c	(revision 57789)
@@ -832,11 +832,7 @@ rb_str_format(int argc, const VALUE *arg https://github.com/ruby/ruby/blob/trunk/sprintf.c#L832
 	      bin_retry:
 		switch (TYPE(val)) {
 		  case T_FLOAT:
-		    if (FIXABLE(RFLOAT_VALUE(val))) {
-			val = LONG2FIX((long)RFLOAT_VALUE(val));
-			goto bin_retry;
-		    }
-		    val = rb_dbl2big(RFLOAT_VALUE(val));
+		    val = rb_dbl2ival(RFLOAT_VALUE(val));
 		    if (FIXNUM_P(val)) goto bin_retry;
 		    bignum = 1;
 		    break;
Index: numeric.c
===================================================================
--- numeric.c	(revision 57788)
+++ numeric.c	(revision 57789)
@@ -1279,10 +1279,7 @@ flo_mod(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1279
 static VALUE
 dbl2ival(double d)
 {
-    if (FIXABLE(d)) {
-	return LONG2FIX((long)d);
-    }
-    return rb_dbl2big(d);
+    return rb_dbl2ival(d);
 }
 
 /*
@@ -1967,7 +1964,6 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/numeric.c#L1964
 flo_floor(int argc, VALUE *argv, VALUE num)
 {
     double number, f;
-    long val;
     int ndigits = 0;
 
     if (rb_check_arity(argc, 0, 1)) {
@@ -1984,11 +1980,7 @@ flo_floor(int argc, VALUE *argv, VALUE n https://github.com/ruby/ruby/blob/trunk/numeric.c#L1980
 	return DBL2NUM(f);
     }
     f = floor(number);
-    if (!FIXABLE(f)) {
-	return rb_dbl2big(f);
-    }
-    val = (long)f;
-    return LONG2FIX(val);
+    return dbl2ival(f);
 }
 
 /*
@@ -2327,16 +2319,11 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/numeric.c#L2319
 flo_to_i(VALUE num)
 {
     double f = RFLOAT_VALUE(num);
-    long val;
 
     if (f > 0.0) f = floor(f);
     if (f < 0.0) f = ceil(f);
 
-    if (!FIXABLE(f)) {
-	return rb_dbl2big(f);
-    }
-    val = (long)f;
-    return LONG2FIX(val);
+    return dbl2ival(f);
 }
 
 /*
@@ -3020,13 +3007,17 @@ VALUE https://github.com/ruby/ruby/blob/trunk/numeric.c#L3007
 rb_num2fix(VALUE val)
 {
     long v;
+    VALUE w;
 
-    if (FIXNUM_P(val)) return val;
-
-    v = rb_num2long(val);
-    if (!FIXABLE(v))
+    if (FIXNUM_P(val)) {
+	return val;
+    }
+    else if (rb_long2fix_overflow((v = rb_num2long(val)), &w)) {
 	rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
-    return LONG2FIX(v);
+    }
+    else {
+	return w;
+    }
 }
 
 #if HAVE_LONG_LONG
Index: object.c
===================================================================
--- object.c	(revision 57788)
+++ object.c	(revision 57789)
@@ -2747,11 +2747,8 @@ rb_convert_to_integer(VALUE val, int bas https://github.com/ruby/ruby/blob/trunk/object.c#L2747
     VALUE tmp;
 
     if (RB_FLOAT_TYPE_P(val)) {
-	double f;
 	if (base != 0) goto arg_error;
-	f = RFLOAT_VALUE(val);
-	if (FIXABLE(f)) return LONG2FIX((long)f);
-	return rb_dbl2big(f);
+	return rb_dbl2ival(RFLOAT_VALUE(val));
     }
     else if (RB_INTEGER_TYPE_P(val)) {
 	if (base != 0) goto arg_error;
Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 57788)
+++ include/ruby/ruby.h	(revision 57789)
@@ -1504,6 +1504,29 @@ rb_integer_type_p(VALUE obj) https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1504
 }
 #endif
 
+static inline int
+rb_long2fix_overflow(long l, VALUE *ptr)
+{
+#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
+    SIGNED_VALUE v;
+    if (__builtin_mul_overflow(l, 2, &v)) {
+	return 1;
+    }
+    else {
+	*ptr = ((VALUE)v) | RUBY_FIXNUM_FLAG;
+	return 0;
+    }
+#else
+    if (RB_FIXABLE(l)) {
+	*ptr = RB_LONG2FIX(l);
+	return 0;
+    }
+    else {
+	return 1;
+    }
+#endif
+}
+
 #if SIZEOF_INT < SIZEOF_LONG
 # define RB_INT2NUM(v) RB_INT2FIX((int)(v))
 # define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v))
@@ -1511,10 +1534,11 @@ rb_integer_type_p(VALUE obj) https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1534
 static inline VALUE
 rb_int2num_inline(int v)
 {
-    if (RB_FIXABLE(v))
-	return RB_INT2FIX(v);
-    else
+    VALUE ret;
+    if (rb_long2fix_overflow(v, &ret))
 	return rb_int2big(v);
+    else
+	return ret;
 }
 #define RB_INT2NUM(x) rb_int2num_inline(x)
 
@@ -1534,10 +1558,11 @@ rb_uint2num_inline(unsigned int v) https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1558
 static inline VALUE
 rb_long2num_inline(long v)
 {
-    if (RB_FIXABLE(v))
-	return RB_LONG2FIX(v);
-    else
+    VALUE ret;
+    if (rb_long2fix_overflow(v, &ret))
 	return rb_int2big(v);
+    else
+	return ret;
 }
 #define RB_LONG2NUM(x) rb_long2num_inline(x)
 
Index: insns.def
===================================================================
--- insns.def	(revision 57788)
+++ insns.def	(revision 57789)
@@ -1345,7 +1345,7 @@ opt_case_dispatch https://github.com/ruby/ruby/blob/trunk/insns.def#L1345
 	    if (RB_FLOAT_TYPE_P(key)) {
 		double kval = RFLOAT_VALUE(key);
 		if (!isinf(kval) && modf(kval, &kval) == 0.0) {
-		    key = FIXABLE(kval) ? LONG2FIX((long)kval) : rb_dbl2big(kval);
+		    key = rb_dbl2ival(kval);
 		}
 	    }
 	    if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
Index: internal.h
===================================================================
--- internal.h	(revision 57788)
+++ internal.h	(revision 57789)
@@ -1383,6 +1383,18 @@ rb_float_new_inline(double d) https://github.com/ruby/ruby/blob/trunk/internal.h#L1383
 #define rb_float_value(v) rb_float_value_inline(v)
 #define rb_float_new(d)   rb_float_new_inline(d)
 
+static inline VALUE
+rb_dbl2ival(double d)
+{
+    VALUE val;
+    if (rb_long2fix_overflow(d, &val)) {
+	return rb_dbl2big(d);
+    }
+    else {
+	return val;
+    }
+}
+
 /* object.c */
 void rb_obj_copy_ivar(VALUE dest, VALUE obj);
 CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2));
Index: bignum.c
===================================================================
--- bignum.c	(revision 57788)
+++ bignum.c	(revision 57789)
@@ -3184,15 +3184,13 @@ rb_int2big(SIGNED_VALUE n) https://github.com/ruby/ruby/blob/trunk/bignum.c#L3184
 VALUE
 rb_uint2inum(VALUE n)
 {
-    if (POSFIXABLE(n)) return LONG2FIX(n);
-    return rb_uint2big(n);
+    return ULONG2NUM(n);
 }
 
 VALUE
 rb_int2inum(SIGNED_VALUE n)
 {
-    if (FIXABLE(n)) return LONG2FIX(n);
-    return rb_int2big(n);
+    return LONG2NUM(n);
 }
 
 void
@@ -4438,8 +4436,18 @@ rb_ull2inum(unsigned LONG_LONG n) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4436
 VALUE
 rb_ll2inum(LONG_LONG n)
 {
+#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
+    SIGNED_VALUE v;
+    if (__builtin_mul_overflow(n, 2, &v)) {
+	return rb_ll2big(n);
+    }
+    else {
+	return ((VALUE)v) | RUBY_FIXNUM_FLAG;
+    }
+#else
     if (FIXABLE(n)) return LONG2FIX(n);
     return rb_ll2big(n);
+#endif
 }
 
 #endif  /* HAVE_LONG_LONG */
Index: compile.c
===================================================================
--- compile.c	(revision 57788)
+++ compile.c	(revision 57789)
@@ -3190,7 +3190,7 @@ case_when_optimizable_literal(NODE *node https://github.com/ruby/ruby/blob/trunk/compile.c#L3190
 	double ival;
 	if (RB_TYPE_P(v, T_FLOAT) &&
 	    modf(RFLOAT_VALUE(v), &ival) == 0.0) {
-	    return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
+	    return rb_dbl2ival(ival);
 	}
 	if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
 	    return v;

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

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