mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57789 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
cf2a68662a
commit
74cdd893eb
8 changed files with 71 additions and 42 deletions
16
bignum.c
16
bignum.c
|
@ -3184,15 +3184,13 @@ rb_int2big(SIGNED_VALUE n)
|
||||||
VALUE
|
VALUE
|
||||||
rb_uint2inum(VALUE n)
|
rb_uint2inum(VALUE n)
|
||||||
{
|
{
|
||||||
if (POSFIXABLE(n)) return LONG2FIX(n);
|
return ULONG2NUM(n);
|
||||||
return rb_uint2big(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_int2inum(SIGNED_VALUE n)
|
rb_int2inum(SIGNED_VALUE n)
|
||||||
{
|
{
|
||||||
if (FIXABLE(n)) return LONG2FIX(n);
|
return LONG2NUM(n);
|
||||||
return rb_int2big(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -4438,8 +4436,18 @@ rb_ull2inum(unsigned LONG_LONG n)
|
||||||
VALUE
|
VALUE
|
||||||
rb_ll2inum(LONG_LONG n)
|
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);
|
if (FIXABLE(n)) return LONG2FIX(n);
|
||||||
return rb_ll2big(n);
|
return rb_ll2big(n);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_LONG_LONG */
|
#endif /* HAVE_LONG_LONG */
|
||||||
|
|
|
@ -3190,7 +3190,7 @@ case_when_optimizable_literal(NODE *node)
|
||||||
double ival;
|
double ival;
|
||||||
if (RB_TYPE_P(v, T_FLOAT) &&
|
if (RB_TYPE_P(v, T_FLOAT) &&
|
||||||
modf(RFLOAT_VALUE(v), &ival) == 0.0) {
|
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)) {
|
if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -1504,6 +1504,29 @@ rb_integer_type_p(VALUE obj)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#if SIZEOF_INT < SIZEOF_LONG
|
||||||
# define RB_INT2NUM(v) RB_INT2FIX((int)(v))
|
# define RB_INT2NUM(v) RB_INT2FIX((int)(v))
|
||||||
# define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v))
|
# define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v))
|
||||||
|
@ -1511,10 +1534,11 @@ rb_integer_type_p(VALUE obj)
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
rb_int2num_inline(int v)
|
rb_int2num_inline(int v)
|
||||||
{
|
{
|
||||||
if (RB_FIXABLE(v))
|
VALUE ret;
|
||||||
return RB_INT2FIX(v);
|
if (rb_long2fix_overflow(v, &ret))
|
||||||
else
|
|
||||||
return rb_int2big(v);
|
return rb_int2big(v);
|
||||||
|
else
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#define RB_INT2NUM(x) rb_int2num_inline(x)
|
#define RB_INT2NUM(x) rb_int2num_inline(x)
|
||||||
|
|
||||||
|
@ -1534,10 +1558,11 @@ rb_uint2num_inline(unsigned int v)
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
rb_long2num_inline(long v)
|
rb_long2num_inline(long v)
|
||||||
{
|
{
|
||||||
if (RB_FIXABLE(v))
|
VALUE ret;
|
||||||
return RB_LONG2FIX(v);
|
if (rb_long2fix_overflow(v, &ret))
|
||||||
else
|
|
||||||
return rb_int2big(v);
|
return rb_int2big(v);
|
||||||
|
else
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#define RB_LONG2NUM(x) rb_long2num_inline(x)
|
#define RB_LONG2NUM(x) rb_long2num_inline(x)
|
||||||
|
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ opt_case_dispatch
|
||||||
if (RB_FLOAT_TYPE_P(key)) {
|
if (RB_FLOAT_TYPE_P(key)) {
|
||||||
double kval = RFLOAT_VALUE(key);
|
double kval = RFLOAT_VALUE(key);
|
||||||
if (!isinf(kval) && modf(kval, &kval) == 0.0) {
|
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)) {
|
if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
|
||||||
|
|
12
internal.h
12
internal.h
|
@ -1383,6 +1383,18 @@ rb_float_new_inline(double d)
|
||||||
#define rb_float_value(v) rb_float_value_inline(v)
|
#define rb_float_value(v) rb_float_value_inline(v)
|
||||||
#define rb_float_new(d) rb_float_new_inline(d)
|
#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 */
|
/* object.c */
|
||||||
void rb_obj_copy_ivar(VALUE dest, VALUE obj);
|
void rb_obj_copy_ivar(VALUE dest, VALUE obj);
|
||||||
CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2));
|
CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2));
|
||||||
|
|
33
numeric.c
33
numeric.c
|
@ -1279,10 +1279,7 @@ flo_mod(VALUE x, VALUE y)
|
||||||
static VALUE
|
static VALUE
|
||||||
dbl2ival(double d)
|
dbl2ival(double d)
|
||||||
{
|
{
|
||||||
if (FIXABLE(d)) {
|
return rb_dbl2ival(d);
|
||||||
return LONG2FIX((long)d);
|
|
||||||
}
|
|
||||||
return rb_dbl2big(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1967,7 +1964,6 @@ static VALUE
|
||||||
flo_floor(int argc, VALUE *argv, VALUE num)
|
flo_floor(int argc, VALUE *argv, VALUE num)
|
||||||
{
|
{
|
||||||
double number, f;
|
double number, f;
|
||||||
long val;
|
|
||||||
int ndigits = 0;
|
int ndigits = 0;
|
||||||
|
|
||||||
if (rb_check_arity(argc, 0, 1)) {
|
if (rb_check_arity(argc, 0, 1)) {
|
||||||
|
@ -1984,11 +1980,7 @@ flo_floor(int argc, VALUE *argv, VALUE num)
|
||||||
return DBL2NUM(f);
|
return DBL2NUM(f);
|
||||||
}
|
}
|
||||||
f = floor(number);
|
f = floor(number);
|
||||||
if (!FIXABLE(f)) {
|
return dbl2ival(f);
|
||||||
return rb_dbl2big(f);
|
|
||||||
}
|
|
||||||
val = (long)f;
|
|
||||||
return LONG2FIX(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2327,16 +2319,11 @@ static VALUE
|
||||||
flo_to_i(VALUE num)
|
flo_to_i(VALUE num)
|
||||||
{
|
{
|
||||||
double f = RFLOAT_VALUE(num);
|
double f = RFLOAT_VALUE(num);
|
||||||
long val;
|
|
||||||
|
|
||||||
if (f > 0.0) f = floor(f);
|
if (f > 0.0) f = floor(f);
|
||||||
if (f < 0.0) f = ceil(f);
|
if (f < 0.0) f = ceil(f);
|
||||||
|
|
||||||
if (!FIXABLE(f)) {
|
return dbl2ival(f);
|
||||||
return rb_dbl2big(f);
|
|
||||||
}
|
|
||||||
val = (long)f;
|
|
||||||
return LONG2FIX(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3020,13 +3007,17 @@ VALUE
|
||||||
rb_num2fix(VALUE val)
|
rb_num2fix(VALUE val)
|
||||||
{
|
{
|
||||||
long v;
|
long v;
|
||||||
|
VALUE w;
|
||||||
|
|
||||||
if (FIXNUM_P(val)) return val;
|
if (FIXNUM_P(val)) {
|
||||||
|
return val;
|
||||||
v = rb_num2long(val);
|
}
|
||||||
if (!FIXABLE(v))
|
else if (rb_long2fix_overflow((v = rb_num2long(val)), &w)) {
|
||||||
rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
|
rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
|
||||||
return LONG2FIX(v);
|
}
|
||||||
|
else {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_LONG_LONG
|
#if HAVE_LONG_LONG
|
||||||
|
|
5
object.c
5
object.c
|
@ -2747,11 +2747,8 @@ rb_convert_to_integer(VALUE val, int base)
|
||||||
VALUE tmp;
|
VALUE tmp;
|
||||||
|
|
||||||
if (RB_FLOAT_TYPE_P(val)) {
|
if (RB_FLOAT_TYPE_P(val)) {
|
||||||
double f;
|
|
||||||
if (base != 0) goto arg_error;
|
if (base != 0) goto arg_error;
|
||||||
f = RFLOAT_VALUE(val);
|
return rb_dbl2ival(RFLOAT_VALUE(val));
|
||||||
if (FIXABLE(f)) return LONG2FIX((long)f);
|
|
||||||
return rb_dbl2big(f);
|
|
||||||
}
|
}
|
||||||
else if (RB_INTEGER_TYPE_P(val)) {
|
else if (RB_INTEGER_TYPE_P(val)) {
|
||||||
if (base != 0) goto arg_error;
|
if (base != 0) goto arg_error;
|
||||||
|
|
|
@ -832,11 +832,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
||||||
bin_retry:
|
bin_retry:
|
||||||
switch (TYPE(val)) {
|
switch (TYPE(val)) {
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
if (FIXABLE(RFLOAT_VALUE(val))) {
|
val = rb_dbl2ival(RFLOAT_VALUE(val));
|
||||||
val = LONG2FIX((long)RFLOAT_VALUE(val));
|
|
||||||
goto bin_retry;
|
|
||||||
}
|
|
||||||
val = rb_dbl2big(RFLOAT_VALUE(val));
|
|
||||||
if (FIXNUM_P(val)) goto bin_retry;
|
if (FIXNUM_P(val)) goto bin_retry;
|
||||||
bignum = 1;
|
bignum = 1;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Reference in a new issue