1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Use ADD instead of MUL

* On recent CPUs, 2-operand MUL's latency is 3 cycle but ADD is 1 cycle.
* clang Optimizes `MUL rax,2` into `ADD rax,rax` but gcc7 doesn't.
* LONG2FIX is compiled into `lea r14,[r15+r15*1+0x1]`; this is 1cycle
  and run in parallel if the branch prediction is correct.
* Note that old (RB_POSFIXABLE(f) && RB_NEGFIXABLE(f)) is usually uses
  following instructions.
  * movabs rax,0x4000000000000000
  * add    rax,rdi
  * js
  It needs large immediate and Macro-Fusion is not applied.
  ADD and JO is much smaller though it is also Macro-Fusion unfriendly.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57793 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2017-03-07 03:35:47 +00:00
parent d4c598c441
commit ac6f08df23
2 changed files with 5 additions and 22 deletions

View file

@ -4436,18 +4436,8 @@ 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 */

View file

@ -359,7 +359,11 @@ rb_fix2ulong(VALUE x)
#define RB_FIXNUM_P(f) (((int)(SIGNED_VALUE)(f))&RUBY_FIXNUM_FLAG) #define RB_FIXNUM_P(f) (((int)(SIGNED_VALUE)(f))&RUBY_FIXNUM_FLAG)
#define RB_POSFIXABLE(f) ((f) < RUBY_FIXNUM_MAX+1) #define RB_POSFIXABLE(f) ((f) < RUBY_FIXNUM_MAX+1)
#define RB_NEGFIXABLE(f) ((f) >= RUBY_FIXNUM_MIN) #define RB_NEGFIXABLE(f) ((f) >= RUBY_FIXNUM_MIN)
#define RB_FIXABLE(f) (RB_POSFIXABLE(f) && RB_NEGFIXABLE(f)) #if defined HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW
# define RB_FIXABLE(f) ({SIGNED_VALUE a=(f),c; !__builtin_add_overflow(a, a, &c);})
#else
# define RB_FIXABLE(f) (RB_POSFIXABLE(f) && RB_NEGFIXABLE(f))
#endif
#define FIX2LONG(x) RB_FIX2LONG(x) #define FIX2LONG(x) RB_FIX2LONG(x)
#define FIX2ULONG(x) RB_FIX2ULONG(x) #define FIX2ULONG(x) RB_FIX2ULONG(x)
#define FIXNUM_P(f) RB_FIXNUM_P(f) #define FIXNUM_P(f) RB_FIXNUM_P(f)
@ -1507,16 +1511,6 @@ rb_integer_type_p(VALUE obj)
static inline int static inline int
rb_long2fix_overflow(long l, VALUE *ptr) 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)) { if (RB_FIXABLE(l)) {
*ptr = RB_LONG2FIX(l); *ptr = RB_LONG2FIX(l);
return 0; return 0;
@ -1524,7 +1518,6 @@ rb_long2fix_overflow(long l, VALUE *ptr)
else { else {
return 1; return 1;
} }
#endif
} }
#if SIZEOF_INT < SIZEOF_LONG #if SIZEOF_INT < SIZEOF_LONG