aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--insns.def17
2 files changed, 21 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index cd43b4a272..6be1c45802 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Tue Jun 28 02:41:32 2016 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * insns.def (opt_plus): use `- 1` instead of `& (~1)` to allow
+ compilers to use x86 LEA instruction (3 operand).
+ Even if 3 operand LEA's latency is 3 cycle after SandyBridge,
+ it reduces code size and can be faster because of super scalar.
+
+ * insns.def (opt_plus): calculate and use rb_int2big.
+ On positive Fixnum overflow, `recv - 1 + obj` doesn't carry
+ because recv's msb and obj's msb are 0, and resulted msb is 1.
+ Therefore simply rshift and cast as signed long works fine.
+ On negative Fixnum overflow, it will carry because both arguments'
+ msb are 1, and resulted msb is also 1.
+ In this case it needs to restore carried sign bit after rshift.
+
Mon Jun 27 16:58:32 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/fileutils.rb (FileUtils#install): accecpt symbolic mode, as
diff --git a/insns.def b/insns.def
index cdc82872ab..6a3a39cae8 100644
--- a/insns.def
+++ b/insns.def
@@ -1381,18 +1381,13 @@ opt_plus
BASIC_OP_UNREDEFINED_P(BOP_PLUS,INTEGER_REDEFINED_OP_FLAG)) {
/* fixnum + fixnum */
#ifndef LONG_LONG_VALUE
- val = (recv + (obj & (~1)));
- if ((~(recv ^ obj) & (recv ^ val)) &
- ((VALUE)0x01 << ((sizeof(VALUE) * CHAR_BIT) - 1))) {
- val = rb_big_plus(rb_int2big(FIX2LONG(recv)),
- rb_int2big(FIX2LONG(obj)));
- }
+ VALUE msb = (VALUE)1 << ((sizeof(VALUE) * CHAR_BIT) - 1);
+ val = recv - 1 + obj;
+ if ((~(recv ^ obj) & (recv ^ val)) & msb) {
+ val = rb_int2big((SIGNED_VALUE)((val>>1) | (recv & msb)));
+ }
#else
- long a, b, c;
- a = FIX2LONG(recv);
- b = FIX2LONG(obj);
- c = a + b;
- val = LONG2NUM(c);
+ val = LONG2NUM(FIX2LONG(recv) + FIX2LONG(obj));
#endif
}
else if (FLONUM_2_P(recv, obj) &&