aboutsummaryrefslogtreecommitdiffstats
path: root/insns.def
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-02-02 15:54:51 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-02-02 15:54:51 +0000
commit14b58d799bcc0c4457b6ff0010dcce2e4669a4fd (patch)
tree1a1526b8206577a2b172836d875fc904d3b33f7f /insns.def
parent9ae47fb45bcc531bcc289411a7a48281011176f1 (diff)
downloadruby-14b58d799bcc0c4457b6ff0010dcce2e4669a4fd.tar.gz
Use carry flag to reduce instructions
NOTE: (1) Fixnum's LSB is always 1. It means you can always run `x - 1` without overflow. (2) Of course `z = x + (y-1)` may overflow. Now z's LSB is always 1, and the MSB of true result is also 1. You can get true result in long as `(1<<63)|(z>>1)`, and it equals to `(z<<63)|(z>>1)` == `ror(z)`. GCC and Clang have __builtin_add_ovewflow: * https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html * https://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'insns.def')
-rw-r--r--insns.def18
1 files changed, 2 insertions, 16 deletions
diff --git a/insns.def b/insns.def
index 4dc4975b6a..9bae14b5a9 100644
--- a/insns.def
+++ b/insns.def
@@ -1373,16 +1373,7 @@ opt_plus
{
if (FIXNUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_PLUS,INTEGER_REDEFINED_OP_FLAG)) {
- /* fixnum + fixnum */
-#ifndef LONG_LONG_VALUE
- 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
- val = LONG2NUM(FIX2LONG(recv) + FIX2LONG(obj));
-#endif
+ val = rb_fix_plus_fix(recv, obj);
}
else if (FLONUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
@@ -1426,12 +1417,7 @@ opt_minus
{
if (FIXNUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
- long a, b, c;
-
- a = FIX2LONG(recv);
- b = FIX2LONG(obj);
- c = a - b;
- val = LONG2NUM(c);
+ val = rb_fix_minus_fix(recv, obj);
}
else if (FLONUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {