aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--insns.def20
-rw-r--r--internal.h28
-rw-r--r--numeric.c27
-rw-r--r--time.c52
5 files changed, 46 insertions, 96 deletions
diff --git a/ChangeLog b/ChangeLog
index b14b9d6c78..d8d93a2d1c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Sun Mar 20 20:10:14 2016 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * internal.h (DLONG): defined if long is 32bit (and LONG_LONG is 64bit;
+ but LONG_LONG is always defined as 64bit), or there's int128_t.
+
+ * internal.h (DL2NUM): defined if DLONG is defined.
+
+ * internal.h (rb_fix_mul_fix): defined for `Fixnum * Fixnum`.
+
+ * insns.def (opt_mul): use rb_fix_mul_fix().
+
+ * numeric.c (fix_mul): ditto.
+
+ * time.c (mul): ditto.
+
Sun Mar 20 18:53:49 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* numeric.c (fix_gt, fix_ge, fix_lt, fix_le): optimize comparisons
diff --git a/insns.def b/insns.def
index 5b08d0625a..b1e8265ce8 100644
--- a/insns.def
+++ b/insns.def
@@ -1487,25 +1487,7 @@ opt_mult
{
if (FIXNUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_MULT, FIXNUM_REDEFINED_OP_FLAG)) {
- long a = FIX2LONG(recv);
-#ifdef HAVE_INT128_T
- VALUE rb_int128t2big(int128_t n);
- int128_t r = (int128_t)a * (int128_t)FIX2LONG(obj);
- if (RB_FIXABLE(r)) {
- val = LONG2FIX((long)r);
- }
- else {
- val = rb_int128t2big(r);
- }
-#else
- long b = FIX2LONG(obj);
- if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
- val = rb_big_mul(rb_int2big(a), rb_int2big(b));
- }
- else {
- val = LONG2FIX(a * b);
- }
-#endif
+ val = rb_fix_mul_fix(recv, obj);
}
else if (FLONUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
diff --git a/internal.h b/internal.h
index c60f21947f..f28d050b12 100644
--- a/internal.h
+++ b/internal.h
@@ -266,6 +266,34 @@ nlz_int128(uint128_t x)
}
#endif
+#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
+# define DLONG LONG_LONG
+# define DL2NUM(x) LL2NUM(x)
+#elif defined(HAVE_INT128_T)
+# define DLONG int128_t
+# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x))
+#endif
+
+VALUE rb_int128t2big(int128_t n);
+
+/* arguments must be Fixnum */
+static inline VALUE
+rb_fix_mul_fix(VALUE x, VALUE y)
+{
+ long lx = FIX2LONG(x);
+ long ly = FIX2LONG(y);
+#ifdef DLONG
+ return DL2NUM((DLONG)lx * (DLONG)ly);
+#else
+ if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
+ return rb_big_mul(rb_int2big(a), rb_int2big(b));
+ }
+ else {
+ return LONG2FIX(a * b);
+ }
+#endif
+}
+
/*
* This behaves different from C99 for negative arguments.
* Note that div may overflow fixnum.
diff --git a/numeric.c b/numeric.c
index 4293374a64..f95e93c179 100644
--- a/numeric.c
+++ b/numeric.c
@@ -3085,32 +3085,7 @@ static VALUE
fix_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
-#ifdef __HP_cc
-/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
- volatile
-#endif
- long a, b;
-#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
- LONG_LONG d;
-#else
- VALUE r;
-#endif
-
- a = FIX2LONG(x);
- b = FIX2LONG(y);
-
-#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
- d = (LONG_LONG)a * b;
- if (FIXABLE(d)) return LONG2FIX(d);
- return rb_ll2inum(d);
-#else
- if (a == 0) return x;
- if (MUL_OVERFLOW_FIXNUM_P(a, b))
- r = rb_big_mul(rb_int2big(a), rb_int2big(b));
- else
- r = LONG2FIX(a * b);
- return r;
-#endif
+ return rb_fix_mul_fix(x, y);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
return rb_big_mul(y, x);
diff --git a/time.c b/time.c
index c51bd5bff7..38b3a68481 100644
--- a/time.c
+++ b/time.c
@@ -91,61 +91,11 @@ sub(VALUE x, VALUE y)
return rb_funcall(x, '-', 1, y);
}
-#if !(HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG)
-static int
-long_mul(long x, long y, long *z)
-{
- unsigned long a, b, c;
- int s;
- if (x == 0 || y == 0) {
- *z = 0;
- return 1;
- }
- if (x < 0) {
- s = -1;
- a = (unsigned long)-x;
- }
- else {
- s = 1;
- a = (unsigned long)x;
- }
- if (y < 0) {
- s = -s;
- b = (unsigned long)-y;
- }
- else {
- b = (unsigned long)y;
- }
- if (a <= ULONG_MAX / b) {
- c = a * b;
- if (s < 0) {
- if (c <= (unsigned long)LONG_MAX + 1) {
- *z = -(long)c;
- return 1;
- }
- }
- else {
- if (c <= (unsigned long)LONG_MAX) {
- *z = (long)c;
- return 1;
- }
- }
- }
- return 0;
-}
-#endif
-
static VALUE
mul(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y)) {
-#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
- return LL2NUM((LONG_LONG)FIX2LONG(x) * FIX2LONG(y));
-#else
- long z;
- if (long_mul(FIX2LONG(x), FIX2LONG(y), &z))
- return LONG2NUM(z);
-#endif
+ rb_fix_mul_fix(x, y);
}
if (RB_TYPE_P(x, T_BIGNUM))
return rb_big_mul(x, y);