aboutsummaryrefslogtreecommitdiff
path: root/gcc/double-int.c
diff options
context:
space:
mode:
authorLawrence Crowl <crowl@google.com>2012-09-24 18:22:31 +0000
committerLawrence Crowl <crowl@gcc.gnu.org>2012-09-24 18:22:31 +0000
commit9be0ac8c9e638bc1b52b83d34a98e8176af645e1 (patch)
tree023b0bf502c0f425e346dd501e463d522b3de28e /gcc/double-int.c
parentee38ecd4066dc3af0b893f2f4cda42d7938fa951 (diff)
downloadgcc-9be0ac8c9e638bc1b52b83d34a98e8176af645e1.zip
gcc-9be0ac8c9e638bc1b52b83d34a98e8176af645e1.tar.gz
gcc-9be0ac8c9e638bc1b52b83d34a98e8176af645e1.tar.bz2
Finish conversion of uses of double_int to the new API.
Some old functionality required new interfaces, and these have been added to double-int.[hc]: double_int::from_pair - static constructor function wide_mul_with_sign - double-wide multiply instruction sub_with_overflow - subtraction with overlow testing neg_with_overflow - negation with overlow testing divmod_with_overflow - div and mod with overlow testing This patch corrects the bootstrap problem on HPPA, via the addition of sub_with_overflow. (The overflow properties of negation and addition are different from subtraction.) The prior two generations of the interface have been removed. Some of these old interfaces are still used as static implementation in double-int.c. The changed compiler appears 0.321% faster with 80% confidence of being faster. Tested on x86_64, HPPA, and SPARC. However, there are changes to the avr config files, and I have not tested those. Index: gcc/java/ChangeLog 2012-09-24 Lawrence Crowl <crowl@google.com> * decl.c (java_init_decl_processing): Change to new double_int API. * jcf-parse.c (get_constant): Likewise. * boehm.c (mark_reference_fields): Likewise. (get_boehm_type_descriptor): Likewise. Index: gcc/ChangeLog 2012-09-24 Lawrence Crowl <crowl@google.com> * double-int.h (double_int::from_pair): New. (double_int::wide_mul_with_sign): New. (double_int::sub_with_overflow): New. (double_int::neg_with_overflow): New. (double_int::divmod_with_overflow): New. (shwi_to_double_int): Remove. (uhwi_to_double_int): Remove. (double_int_to_shwi): Remove. (double_int_to_uhwi): Remove. (double_int_fits_in_uhwi_p): Remove. (double_int_fits_in_shwi_p): Remove. (double_int_fits_in_hwi_p): Remove. (double_int_mul): Remove. (double_int_mul_with_sign): Remove. (double_int_add): Remove. (double_int_sub): Remove. (double_int_neg): Remove. (double_int_div): Remove. (double_int_sdiv): Remove. (double_int_udiv): Remove. (double_int_mod): Remove. (double_int_smod): Remove. (double_int_umod): Remove. (double_int_divmod): Remove. (double_int_sdivmod): Remove. (double_int_udivmod): Remove. (double_int_multiple_of): Remove. (double_int_setbit): Remove. (double_int_ctz): Remove. (double_int_not): Remove. (double_int_ior): Remove. (double_int_and): Remove. (double_int_and_not): Remove. (double_int_xor): Remove. (double_int_lshift): Remove. (double_int_rshift): Remove. (double_int_lrotate): Remove. (double_int_rrotate): Remove. (double_int_negative_p): Remove. (double_int_cmp): Remove. (double_int_scmp): Remove. (double_int_ucmp): Remove. (double_int_max): Remove. (double_int_smax): Remove. (double_int_umax): Remove. (double_int_min): Remove. (double_int_smin): Remove. (double_int_umin): Remove. (double_int_ext): Remove. (double_int_sext): Remove. (double_int_zext): Remove. (double_int_mask): Remove. (double_int_max_value): Remove. (double_int_min_value): Remove. (double_int_zero_p): Remove. (double_int_one_p): Remove. (double_int_minus_one_p): Remove. (double_int_equal_p): Remove. (double_int_popcount): Remove. (extern add_double_with_sign): Remove. (#define add_double): Remove. (extern neg_double): Remove. (extern mul_double_with_sign): Remove. (extern mul_double_wide_with_sign): Remove. (#define mul_double): Remove. (extern lshift_double): Remove. (extern div_and_round_double): Remove. * double-int.c (add_double_with_sign): Make static. (#defined add_double): Localized from header. (neg_double): Make static. (mul_double_with_sign): Make static. (mul_double_wide_with_sign): Make static. (#defined mul_double): Localized from header. (lshift_double): Make static. (div_and_round_double): Make static. (double_int::wide_mul_with_sign): New. (double_int::sub_with_overflow): New. (double_int::neg_with_overflow): New. (double_int::divmod_with_overflow): New. * emit-rtl.c (init_emit_once): Change to new double_int API. * explow.c (plus_constant): Likewise. * expmed.c (choose_multiplier): Likewise. * fold-const.c (#define OVERFLOW_SUM_SIGN): Remove. (int_const_binop_1): Change to new double_int API. (fold_div_compare): Likewise. (maybe_canonicalize_comparison): Likewise. (pointer_may_wrap_p): Likewise. (fold_negate_const): Likewise. (fold_abs_const): Likewise. * simplify-rtx.c (simplify_const_unary_operation): Likewise. (simplify_const_binary_operation): Likewise. * tree-chrec.c (tree_fold_binomial): Likewise. * tree-vrp.c (extract_range_from_binary_expr_1): Likewise. * config/sparc/sparc.c (sparc_fold_builtin): Likewise. * config/avr/avr.c (avr_double_int_push_digit): Likewise. (avr_map): Likewise. (avr_map_decompose): Likewise. (avr_out_insert_bits): Likewise. Index: gcc/cp/ChangeLog 2012-09-24 Lawrence Crowl <crowl@google.com> * init.c (build_new_1): Change to new double_int API. * decl.c (build_enumerator): Likewise. * typeck2.c (process_init_constructor_array): Likewise. * mangle.c (write_array_type): Likewise. Index: gcc/fortran/ChangeLog 2012-09-24 Lawrence Crowl <crowl@google.com> * trans-expr.c (gfc_conv_cst_int_power): Change to new double_int API. * target-memory.c (gfc_interpret_logical): Likewise. From-SVN: r191675
Diffstat (limited to 'gcc/double-int.c')
-rw-r--r--gcc/double-int.c94
1 files changed, 88 insertions, 6 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c
index f3d5e8b..41a4148 100644
--- a/gcc/double-int.c
+++ b/gcc/double-int.c
@@ -23,6 +23,41 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h" /* For SHIFT_COUNT_TRUNCATED. */
#include "tree.h"
+static int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
+ bool);
+
+#define add_double(l1,h1,l2,h2,lv,hv) \
+ add_double_with_sign (l1, h1, l2, h2, lv, hv, false)
+
+static int neg_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
+
+static int mul_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
+ bool);
+
+static int mul_double_wide_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
+ bool);
+
+#define mul_double(l1,h1,l2,h2,lv,hv) \
+ mul_double_with_sign (l1, h1, l2, h2, lv, hv, false)
+
+static void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ HOST_WIDE_INT, unsigned int,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
+
+static int div_and_round_double (unsigned, int, unsigned HOST_WIDE_INT,
+ HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ HOST_WIDE_INT, unsigned HOST_WIDE_INT *,
+ HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
+ HOST_WIDE_INT *);
+
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
and SUM1. Then this yields nonzero if overflow occurred during the
@@ -75,7 +110,7 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
One argument is L1 and H1; the other, L2 and H2.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-int
+static int
add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
@@ -105,7 +140,7 @@ add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-int
+static int
neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
{
@@ -129,7 +164,7 @@ neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
One argument is L1 and H1; the other, L2 and H2.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-int
+static int
mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
@@ -143,7 +178,7 @@ mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
unsigned_p);
}
-int
+static int
mul_double_wide_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
@@ -269,7 +304,7 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-void
+static void
lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
HOST_WIDE_INT count, unsigned int prec,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith)
@@ -335,7 +370,7 @@ lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
Return nonzero if the operation overflows.
UNS nonzero says do unsigned division. */
-int
+static int
div_and_round_double (unsigned code, int uns,
/* num == numerator == dividend */
unsigned HOST_WIDE_INT lnum_orig,
@@ -762,6 +797,19 @@ double_int::mul_with_sign (double_int b, bool unsigned_p, bool *overflow) const
return ret;
}
+double_int
+double_int::wide_mul_with_sign (double_int b, bool unsigned_p,
+ double_int *higher, bool *overflow) const
+
+{
+ double_int lower;
+ *overflow = mul_double_wide_with_sign (low, high, b.low, b.high,
+ &lower.low, &lower.high,
+ &higher->low, &higher->high,
+ unsigned_p);
+ return lower;
+}
+
/* Returns A + B. */
double_int
@@ -798,6 +846,19 @@ double_int::operator - (double_int b) const
return ret;
}
+/* Returns A - B. If the operation overflows via inconsistent sign bits,
+ *OVERFLOW is set to nonzero. */
+
+double_int
+double_int::sub_with_overflow (double_int b, bool *overflow) const
+{
+ double_int ret;
+ neg_double (b.low, b.high, &ret.low, &ret.high);
+ add_double (low, high, ret.low, ret.high, &ret.low, &ret.high);
+ *overflow = OVERFLOW_SUM_SIGN (ret.high, b.high, high);
+ return ret;
+}
+
/* Returns -A. */
double_int
@@ -809,12 +870,33 @@ double_int::operator - () const
return ret;
}
+double_int
+double_int::neg_with_overflow (bool *overflow) const
+{
+ double_int ret;
+ *overflow = neg_double (low, high, &ret.low, &ret.high);
+ return ret;
+}
+
/* Returns A / B (computed as unsigned depending on UNS, and rounded as
specified by CODE). CODE is enum tree_code in fact, but double_int.h
must be included before tree.h. The remainder after the division is
stored to MOD. */
double_int
+double_int::divmod_with_overflow (double_int b, bool uns, unsigned code,
+ double_int *mod, bool *overflow) const
+{
+ const double_int &a = *this;
+ double_int ret;
+
+ *overflow = div_and_round_double (code, uns, a.low, a.high,
+ b.low, b.high, &ret.low, &ret.high,
+ &mod->low, &mod->high);
+ return ret;
+}
+
+double_int
double_int::divmod (double_int b, bool uns, unsigned code,
double_int *mod) const
{