From 1e791f438b62a957064f530aa3ceb018cc86eac5 Mon Sep 17 00:00:00 2001
From: naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date: Mon, 27 Jun 2016 18:30:12 +0000
Subject: * 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
---
 insns.def | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

(limited to 'insns.def')

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) &&
-- 
cgit v1.2.3

