aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog101
-rw-r--r--gcc/config/avr/avr.c12
-rw-r--r--gcc/config/sparc/sparc.c39
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/init.c35
-rw-r--r--gcc/cp/mangle.c7
-rw-r--r--gcc/cp/typeck2.c14
-rw-r--r--gcc/double-int.c94
-rw-r--r--gcc/double-int.h460
-rw-r--r--gcc/emit-rtl.c18
-rw-r--r--gcc/explow.c33
-rw-r--r--gcc/expmed.c55
-rw-r--r--gcc/fold-const.c81
-rw-r--r--gcc/fortran/ChangeLog5
-rw-r--r--gcc/fortran/target-memory.c3
-rw-r--r--gcc/fortran/trans-expr.c4
-rw-r--r--gcc/java/ChangeLog7
-rw-r--r--gcc/java/boehm.c6
-rw-r--r--gcc/java/decl.c2
-rw-r--r--gcc/java/jcf-parse.c4
-rw-r--r--gcc/simplify-rtx.c152
-rw-r--r--gcc/tree-chrec.c50
-rw-r--r--gcc/tree-vrp.c23
24 files changed, 450 insertions, 774 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 01536e1..276fead 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,104 @@
+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.
+
2012-09-24 Janis Johnson <janisjo@codesourcery.com>
doc/sourcebuild.texi (Selectors): Document the use of target
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 42c722e..ea36a54 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -10812,10 +10812,10 @@ avr_double_int_push_digit (double_int val, int base,
unsigned HOST_WIDE_INT digit)
{
val = 0 == base
- ? double_int_lshift (val, 32, 64, false)
- : double_int_mul (val, uhwi_to_double_int (base));
+ ? val.llshift (32, 64)
+ : val * double_int::from_uhwi (base);
- return double_int_add (val, uhwi_to_double_int (digit));
+ return val + double_int::from_uhwi (digit);
}
@@ -10824,7 +10824,7 @@ avr_double_int_push_digit (double_int val, int base,
static int
avr_map (double_int f, int x)
{
- return 0xf & double_int_to_uhwi (double_int_rshift (f, 4*x, 64, false));
+ return 0xf & f.lrshift (4*x, 64).to_uhwi ();
}
@@ -10997,7 +10997,7 @@ avr_map_decompose (double_int f, const avr_map_op_t *g, bool val_const_p)
are mapped to 0 and used operands are reloaded to xop[0]. */
xop[0] = all_regs_rtx[24];
- xop[1] = gen_int_mode (double_int_to_uhwi (f_ginv.map), SImode);
+ xop[1] = gen_int_mode (f_ginv.map.to_uhwi (), SImode);
xop[2] = all_regs_rtx[25];
xop[3] = val_used_p ? xop[0] : const0_rtx;
@@ -11093,7 +11093,7 @@ avr_out_insert_bits (rtx *op, int *plen)
else if (flag_print_asm_name)
fprintf (asm_out_file,
ASM_COMMENT_START "map = 0x%08" HOST_LONG_FORMAT "x\n",
- double_int_to_uhwi (map) & GET_MODE_MASK (SImode));
+ map.to_uhwi () & GET_MODE_MASK (SImode));
/* If MAP has fixed points it might be better to initialize the result
with the bits to be inserted instead of moving all bits by hand. */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 0f744e0..fa36901 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -10129,35 +10129,30 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
&& TREE_CODE (arg1) == VECTOR_CST
&& TREE_CODE (arg2) == INTEGER_CST)
{
- int overflow = 0;
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg2);
- HOST_WIDE_INT high = TREE_INT_CST_HIGH (arg2);
+ bool overflow = false;
+ double_int di_arg2 = TREE_INT_CST (arg2);
+ double_int tmp;
unsigned i;
for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
{
- unsigned HOST_WIDE_INT
- low0 = TREE_INT_CST_LOW (VECTOR_CST_ELT (arg0, i)),
- low1 = TREE_INT_CST_LOW (VECTOR_CST_ELT (arg1, i));
- HOST_WIDE_INT
- high0 = TREE_INT_CST_HIGH (VECTOR_CST_ELT (arg0, i));
- HOST_WIDE_INT
- high1 = TREE_INT_CST_HIGH (VECTOR_CST_ELT (arg1, i));
-
- unsigned HOST_WIDE_INT l;
- HOST_WIDE_INT h;
-
- overflow |= neg_double (low1, high1, &l, &h);
- overflow |= add_double (low0, high0, l, h, &l, &h);
- if (h < 0)
- overflow |= neg_double (l, h, &l, &h);
-
- overflow |= add_double (low, high, l, h, &low, &high);
+ double_int e0 = TREE_INT_CST (VECTOR_CST_ELT (arg0, i));
+ double_int e1 = TREE_INT_CST (VECTOR_CST_ELT (arg1, i));
+
+ bool neg1_ovf, neg2_ovf, add1_ovf, add2_ovf;
+
+ tmp = e1.neg_with_overflow (&neg1_ovf);
+ tmp = e0.add_with_sign (tmp, false, &add1_ovf);
+ if (tmp.is_negative ())
+ tmp = tmp.neg_with_overflow (&neg2_ovf);
+
+ tmp = di_arg2.add_with_sign (tmp, false, &add2_ovf);
+ overflow |= neg1_ovf | neg2_ovf | add1_ovf | add2_ovf;
}
- gcc_assert (overflow == 0);
+ gcc_assert (!overflow);
- return build_int_cst_wide (rtype, low, high);
+ return build_int_cst_wide (rtype, tmp.low, tmp.high);
}
default:
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 65c9c2c..c03f66a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+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.
+
2012-09-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50828
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 452f761..6f2c023 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12462,8 +12462,6 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
{
if (TYPE_VALUES (enumtype))
{
- HOST_WIDE_INT hi;
- unsigned HOST_WIDE_INT lo;
tree prev_value;
bool overflowed;
@@ -12479,15 +12477,13 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
value = error_mark_node;
else
{
- overflowed = add_double (TREE_INT_CST_LOW (prev_value),
- TREE_INT_CST_HIGH (prev_value),
- 1, 0, &lo, &hi);
+ double_int di = TREE_INT_CST (prev_value)
+ .add_with_sign (double_int_one,
+ false, &overflowed);
if (!overflowed)
{
- double_int di;
tree type = TREE_TYPE (prev_value);
- bool pos = (TYPE_UNSIGNED (type) || hi >= 0);
- di.low = lo; di.high = hi;
+ bool pos = TYPE_UNSIGNED (type) || !di.is_negative ();
if (!double_int_fits_to_tree_p (type, di))
{
unsigned int itk;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index d097443..b18f600 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2238,11 +2238,11 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
if (TREE_CONSTANT (inner_nelts_cst)
&& TREE_CODE (inner_nelts_cst) == INTEGER_CST)
{
- double_int result;
- if (mul_double (TREE_INT_CST_LOW (inner_nelts_cst),
- TREE_INT_CST_HIGH (inner_nelts_cst),
- inner_nelts_count.low, inner_nelts_count.high,
- &result.low, &result.high))
+ bool overflow;
+ double_int result = TREE_INT_CST (inner_nelts_cst)
+ .mul_with_sign (inner_nelts_count,
+ false, &overflow);
+ if (overflow)
{
if (complain & tf_error)
error ("integer overflow in array size");
@@ -2344,8 +2344,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
/* Maximum available size in bytes. Half of the address space
minus the cookie size. */
double_int max_size
- = double_int_lshift (double_int_one, TYPE_PRECISION (sizetype) - 1,
- HOST_BITS_PER_DOUBLE_INT, false);
+ = double_int_one.llshift (TYPE_PRECISION (sizetype) - 1,
+ HOST_BITS_PER_DOUBLE_INT);
/* Size of the inner array elements. */
double_int inner_size;
/* Maximum number of outer elements which can be allocated. */
@@ -2355,22 +2355,21 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
gcc_assert (TREE_CODE (size) == INTEGER_CST);
cookie_size = targetm.cxx.get_cookie_size (elt_type);
gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST);
- gcc_checking_assert (double_int_ucmp
- (TREE_INT_CST (cookie_size), max_size) < 0);
+ gcc_checking_assert (TREE_INT_CST (cookie_size).ult (max_size));
/* Unconditionally substract the cookie size. This decreases the
maximum object size and is safe even if we choose not to use
a cookie after all. */
- max_size = double_int_sub (max_size, TREE_INT_CST (cookie_size));
- if (mul_double (TREE_INT_CST_LOW (size), TREE_INT_CST_HIGH (size),
- inner_nelts_count.low, inner_nelts_count.high,
- &inner_size.low, &inner_size.high)
- || double_int_ucmp (inner_size, max_size) > 0)
+ max_size -= TREE_INT_CST (cookie_size);
+ bool overflow;
+ inner_size = TREE_INT_CST (size)
+ .mul_with_sign (inner_nelts_count, false, &overflow);
+ if (overflow || inner_size.ugt (max_size))
{
if (complain & tf_error)
error ("size of array is too large");
return error_mark_node;
}
- max_outer_nelts = double_int_udiv (max_size, inner_size, TRUNC_DIV_EXPR);
+ max_outer_nelts = max_size.udiv (inner_size, TRUNC_DIV_EXPR);
/* Only keep the top-most seven bits, to simplify encoding the
constant in the instruction stream. */
{
@@ -2378,10 +2377,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
- (max_outer_nelts.high ? clz_hwi (max_outer_nelts.high)
: (HOST_BITS_PER_WIDE_INT + clz_hwi (max_outer_nelts.low)));
max_outer_nelts
- = double_int_lshift (double_int_rshift
- (max_outer_nelts, shift,
- HOST_BITS_PER_DOUBLE_INT, false),
- shift, HOST_BITS_PER_DOUBLE_INT, false);
+ = max_outer_nelts.lrshift (shift, HOST_BITS_PER_DOUBLE_INT)
+ .llshift (shift, HOST_BITS_PER_DOUBLE_INT);
}
max_outer_nelts_tree = double_int_to_tree (sizetype, max_outer_nelts);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 469953a..13c658b 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3119,12 +3119,11 @@ write_array_type (const tree type)
{
/* The ABI specifies that we should mangle the number of
elements in the array, not the largest allowed index. */
- double_int dmax
- = double_int_add (tree_to_double_int (max), double_int_one);
+ double_int dmax = tree_to_double_int (max) + double_int_one;
/* Truncate the result - this will mangle [0, SIZE_INT_MAX]
number of elements as zero. */
- dmax = double_int_zext (dmax, TYPE_PRECISION (TREE_TYPE (max)));
- gcc_assert (double_int_fits_in_uhwi_p (dmax));
+ dmax = dmax.zext (TYPE_PRECISION (TREE_TYPE (max)));
+ gcc_assert (dmax.fits_uhwi ());
write_unsigned_number (dmax.low);
}
else
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 58b2db6..3dbfcb6 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1058,14 +1058,12 @@ process_init_constructor_array (tree type, tree init,
{
tree domain = TYPE_DOMAIN (type);
if (domain)
- len = double_int_ext
- (double_int_add
- (double_int_sub
- (tree_to_double_int (TYPE_MAX_VALUE (domain)),
- tree_to_double_int (TYPE_MIN_VALUE (domain))),
- double_int_one),
- TYPE_PRECISION (TREE_TYPE (domain)),
- TYPE_UNSIGNED (TREE_TYPE (domain))).low;
+ len = (tree_to_double_int (TYPE_MAX_VALUE (domain))
+ - tree_to_double_int (TYPE_MIN_VALUE (domain))
+ + double_int_one)
+ .ext (TYPE_PRECISION (TREE_TYPE (domain)),
+ TYPE_UNSIGNED (TREE_TYPE (domain)))
+ .low;
else
unbounded = true; /* Take as many as there are. */
}
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
{
diff --git a/gcc/double-int.h b/gcc/double-int.h
index bc7aca1..f4eb6ab 100644
--- a/gcc/double-int.h
+++ b/gcc/double-int.h
@@ -61,6 +61,7 @@ struct double_int
static double_int from_uhwi (unsigned HOST_WIDE_INT cst);
static double_int from_shwi (HOST_WIDE_INT cst);
+ static double_int from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low);
/* No copy assignment operator or destructor to keep the type a POD. */
@@ -105,9 +106,17 @@ struct double_int
/* Arithmetic operation functions. */
+ /* The following operations perform arithmetics modulo 2^precision, so you
+ do not need to call .ext between them, even if you are representing
+ numbers with precision less than HOST_BITS_PER_DOUBLE_INT bits. */
+
double_int set_bit (unsigned) const;
double_int mul_with_sign (double_int, bool unsigned_p, bool *overflow) const;
+ double_int wide_mul_with_sign (double_int, bool unsigned_p,
+ double_int *higher, bool *overflow) const;
double_int add_with_sign (double_int, bool unsigned_p, bool *overflow) const;
+ double_int sub_with_overflow (double_int, bool *overflow) const;
+ double_int neg_with_overflow (bool *overflow) const;
double_int operator * (double_int) const;
double_int operator + (double_int) const;
@@ -131,12 +140,15 @@ struct double_int
/* You must ensure that double_int::ext is called on the operands
of the following operations, if the precision of the numbers
is less than HOST_BITS_PER_DOUBLE_INT bits. */
+
double_int div (double_int, bool, unsigned) const;
double_int sdiv (double_int, unsigned) const;
double_int udiv (double_int, unsigned) const;
double_int mod (double_int, bool, unsigned) const;
double_int smod (double_int, unsigned) const;
double_int umod (double_int, unsigned) const;
+ double_int divmod_with_overflow (double_int, bool, unsigned,
+ double_int *, bool *) const;
double_int divmod (double_int, bool, unsigned, double_int *) const;
double_int sdivmod (double_int, unsigned, double_int *) const;
double_int udivmod (double_int, unsigned, double_int *) const;
@@ -199,13 +211,6 @@ double_int::from_shwi (HOST_WIDE_INT cst)
return r;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-shwi_to_double_int (HOST_WIDE_INT cst)
-{
- return double_int::from_shwi (cst);
-}
-
/* Some useful constants. */
/* FIXME(crowl): Maybe remove after converting callers?
The problem is that a named constant would not be as optimizable,
@@ -229,11 +234,13 @@ double_int::from_uhwi (unsigned HOST_WIDE_INT cst)
return r;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-uhwi_to_double_int (unsigned HOST_WIDE_INT cst)
+inline double_int
+double_int::from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low)
{
- return double_int::from_uhwi (cst);
+ double_int r;
+ r.low = low;
+ r.high = high;
+ return r;
}
inline double_int &
@@ -301,13 +308,6 @@ double_int::to_shwi () const
return (HOST_WIDE_INT) low;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline HOST_WIDE_INT
-double_int_to_shwi (double_int cst)
-{
- return cst.to_shwi ();
-}
-
/* Returns value of CST as an unsigned number. CST must satisfy
double_int::fits_unsigned. */
@@ -317,13 +317,6 @@ double_int::to_uhwi () const
return low;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline unsigned HOST_WIDE_INT
-double_int_to_uhwi (double_int cst)
-{
- return cst.to_uhwi ();
-}
-
/* Returns true if CST fits in unsigned HOST_WIDE_INT. */
inline bool
@@ -332,164 +325,6 @@ double_int::fits_uhwi () const
return high == 0;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline bool
-double_int_fits_in_uhwi_p (double_int cst)
-{
- return cst.fits_uhwi ();
-}
-
-/* Returns true if CST fits in signed HOST_WIDE_INT. */
-
-/* FIXME(crowl): Remove after converting callers. */
-inline bool
-double_int_fits_in_shwi_p (double_int cst)
-{
- return cst.fits_shwi ();
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline bool
-double_int_fits_in_hwi_p (double_int cst, bool uns)
-{
- return cst.fits_hwi (uns);
-}
-
-/* The following operations perform arithmetics modulo 2^precision,
- so you do not need to call double_int_ext between them, even if
- you are representing numbers with precision less than
- HOST_BITS_PER_DOUBLE_INT bits. */
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_mul (double_int a, double_int b)
-{
- return a * b;
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_mul_with_sign (double_int a, double_int b,
- bool unsigned_p, int *overflow)
-{
- bool ovf;
- return a.mul_with_sign (b, unsigned_p, &ovf);
- *overflow = ovf;
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_add (double_int a, double_int b)
-{
- return a + b;
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_sub (double_int a, double_int b)
-{
- return a - b;
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_neg (double_int a)
-{
- return -a;
-}
-
-/* You must ensure that double_int_ext is called on the operands
- of the following operations, if the precision of the numbers
- is less than HOST_BITS_PER_DOUBLE_INT bits. */
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_div (double_int a, double_int b, bool uns, unsigned code)
-{
- return a.div (b, uns, code);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_sdiv (double_int a, double_int b, unsigned code)
-{
- return a.sdiv (b, code);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_udiv (double_int a, double_int b, unsigned code)
-{
- return a.udiv (b, code);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_mod (double_int a, double_int b, bool uns, unsigned code)
-{
- return a.mod (b, uns, code);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_smod (double_int a, double_int b, unsigned code)
-{
- return a.smod (b, code);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_umod (double_int a, double_int b, unsigned code)
-{
- return a.umod (b, code);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_divmod (double_int a, double_int b, bool uns,
- unsigned code, double_int *mod)
-{
- return a.divmod (b, uns, code, mod);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_sdivmod (double_int a, double_int b, unsigned code, double_int *mod)
-{
- return a.sdivmod (b, code, mod);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod)
-{
- return a.udivmod (b, code, mod);
-}
-
-/***/
-
-/* FIXME(crowl): Remove after converting callers. */
-inline bool
-double_int_multiple_of (double_int product, double_int factor,
- bool unsigned_p, double_int *multiple)
-{
- return product.multiple_of (factor, unsigned_p, multiple);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_setbit (double_int a, unsigned bitpos)
-{
- return a.set_bit (bitpos);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline int
-double_int_ctz (double_int a)
-{
- return a.trailing_zeros ();
-}
-
/* Logical operations. */
/* Returns ~A. */
@@ -503,13 +338,6 @@ double_int::operator ~ () const
return result;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-double_int_not (double_int a)
-{
- return ~a;
-}
-
/* Returns A | B. */
inline double_int
@@ -521,13 +349,6 @@ double_int::operator | (double_int b) const
return result;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-double_int_ior (double_int a, double_int b)
-{
- return a | b;
-}
-
/* Returns A & B. */
inline double_int
@@ -539,13 +360,6 @@ double_int::operator & (double_int b) const
return result;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-double_int_and (double_int a, double_int b)
-{
- return a & b;
-}
-
/* Returns A & ~B. */
inline double_int
@@ -557,13 +371,6 @@ double_int::and_not (double_int b) const
return result;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-double_int_and_not (double_int a, double_int b)
-{
- return a.and_not (b);
-}
-
/* Returns A ^ B. */
inline double_int
@@ -575,165 +382,8 @@ double_int::operator ^ (double_int b) const
return result;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline double_int
-double_int_xor (double_int a, double_int b)
-{
- return a ^ b;
-}
-
-
-/* Shift operations. */
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_lshift (double_int a, HOST_WIDE_INT count, unsigned int prec,
- bool arith)
-{
- return a.lshift (count, prec, arith);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec,
- bool arith)
-{
- return a.rshift (count, prec, arith);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_lrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
-{
- return a.lrotate (count, prec);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_rrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
-{
- return a.rrotate (count, prec);
-}
-
-/* Returns true if CST is negative. Of course, CST is considered to
- be signed. */
-
-static inline bool
-double_int_negative_p (double_int cst)
-{
- return cst.high < 0;
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline int
-double_int_cmp (double_int a, double_int b, bool uns)
-{
- return a.cmp (b, uns);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline int
-double_int_scmp (double_int a, double_int b)
-{
- return a.scmp (b);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline int
-double_int_ucmp (double_int a, double_int b)
-{
- return a.ucmp (b);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_max (double_int a, double_int b, bool uns)
-{
- return a.max (b, uns);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_smax (double_int a, double_int b)
-{
- return a.smax (b);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_umax (double_int a, double_int b)
-{
- return a.umax (b);
-}
-
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_min (double_int a, double_int b, bool uns)
-{
- return a.min (b, uns);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_smin (double_int a, double_int b)
-{
- return a.smin (b);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_umin (double_int a, double_int b)
-{
- return a.umin (b);
-}
-
void dump_double_int (FILE *, double_int, bool);
-/* Zero and sign extension of numbers in smaller precisions. */
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_ext (double_int a, unsigned prec, bool uns)
-{
- return a.ext (prec, uns);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_sext (double_int a, unsigned prec)
-{
- return a.sext (prec);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_zext (double_int a, unsigned prec)
-{
- return a.zext (prec);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_mask (unsigned prec)
-{
- return double_int::mask (prec);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_max_value (unsigned int prec, bool uns)
-{
- return double_int::max_value (prec, uns);
-}
-
-/* FIXME(crowl): Remove after converting callers. */
-inline double_int
-double_int_min_value (unsigned int prec, bool uns)
-{
- return double_int::min_value (prec, uns);
-}
-
#define ALL_ONES (~((unsigned HOST_WIDE_INT) 0))
/* The operands of the following comparison functions must be processed
@@ -748,13 +398,6 @@ double_int::is_zero () const
return low == 0 && high == 0;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline bool
-double_int_zero_p (double_int cst)
-{
- return cst.is_zero ();
-}
-
/* Returns true if CST is one. */
inline bool
@@ -763,13 +406,6 @@ double_int::is_one () const
return low == 1 && high == 0;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline bool
-double_int_one_p (double_int cst)
-{
- return cst.is_one ();
-}
-
/* Returns true if CST is minus one. */
inline bool
@@ -778,13 +414,6 @@ double_int::is_minus_one () const
return low == ALL_ONES && high == -1;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline bool
-double_int_minus_one_p (double_int cst)
-{
- return cst.is_minus_one ();
-}
-
/* Returns true if CST is negative. */
inline bool
@@ -801,13 +430,6 @@ double_int::operator == (double_int cst2) const
return low == cst2.low && high == cst2.high;
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline bool
-double_int_equal_p (double_int cst1, double_int cst2)
-{
- return cst1 == cst2;
-}
-
/* Returns true if CST1 != CST2. */
inline bool
@@ -824,52 +446,6 @@ double_int::popcount () const
return popcount_hwi (high) + popcount_hwi (low);
}
-/* FIXME(crowl): Remove after converting callers. */
-static inline int
-double_int_popcount (double_int cst)
-{
- return cst.popcount ();
-}
-
-
-/* Legacy interface with decomposed high/low parts. */
-
-/* FIXME(crowl): Remove after converting callers. */
-extern 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);
-/* FIXME(crowl): Remove after converting callers. */
-#define add_double(l1,h1,l2,h2,lv,hv) \
- add_double_with_sign (l1, h1, l2, h2, lv, hv, false)
-/* FIXME(crowl): Remove after converting callers. */
-extern int neg_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
- unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
-/* FIXME(crowl): Remove after converting callers. */
-extern 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);
-/* FIXME(crowl): Remove after converting callers. */
-extern 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);
-/* FIXME(crowl): Remove after converting callers. */
-#define mul_double(l1,h1,l2,h2,lv,hv) \
- mul_double_with_sign (l1, h1, l2, h2, lv, hv, false)
-/* FIXME(crowl): Remove after converting callers. */
-extern void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
- HOST_WIDE_INT, unsigned int,
- unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
-/* FIXME(crowl): Remove after converting callers. */
-extern 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 *);
-
#ifndef GENERATOR_FILE
/* Conversion to and from GMP integer representations. */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index a65558d..ee6ae22 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -5764,11 +5764,10 @@ init_emit_once (void)
FCONST1(mode).data.high = 0;
FCONST1(mode).data.low = 0;
FCONST1(mode).mode = mode;
- lshift_double (1, 0, GET_MODE_FBIT (mode),
- HOST_BITS_PER_DOUBLE_INT,
- &FCONST1(mode).data.low,
- &FCONST1(mode).data.high,
- SIGNED_FIXED_POINT_MODE_P (mode));
+ FCONST1(mode).data
+ = double_int_one.lshift (GET_MODE_FBIT (mode),
+ HOST_BITS_PER_DOUBLE_INT,
+ SIGNED_FIXED_POINT_MODE_P (mode));
const_tiny_rtx[1][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
FCONST1 (mode), mode);
}
@@ -5787,11 +5786,10 @@ init_emit_once (void)
FCONST1(mode).data.high = 0;
FCONST1(mode).data.low = 0;
FCONST1(mode).mode = mode;
- lshift_double (1, 0, GET_MODE_FBIT (mode),
- HOST_BITS_PER_DOUBLE_INT,
- &FCONST1(mode).data.low,
- &FCONST1(mode).data.high,
- SIGNED_FIXED_POINT_MODE_P (mode));
+ FCONST1(mode).data
+ = double_int_one.lshift (GET_MODE_FBIT (mode),
+ HOST_BITS_PER_DOUBLE_INT,
+ SIGNED_FIXED_POINT_MODE_P (mode));
const_tiny_rtx[1][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
FCONST1 (mode), mode);
}
diff --git a/gcc/explow.c b/gcc/explow.c
index 0563a23..6109832 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -100,36 +100,33 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
case CONST_INT:
if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
{
- unsigned HOST_WIDE_INT l1 = INTVAL (x);
- HOST_WIDE_INT h1 = (l1 >> (HOST_BITS_PER_WIDE_INT - 1)) ? -1 : 0;
- unsigned HOST_WIDE_INT l2 = c;
- HOST_WIDE_INT h2 = c < 0 ? -1 : 0;
- unsigned HOST_WIDE_INT lv;
- HOST_WIDE_INT hv;
-
- if (add_double_with_sign (l1, h1, l2, h2, &lv, &hv, false))
+ double_int di_x = double_int::from_shwi (INTVAL (x));
+ double_int di_c = double_int::from_shwi (c);
+
+ bool overflow;
+ double_int v = di_x.add_with_sign (di_c, false, &overflow);
+ if (overflow)
gcc_unreachable ();
- return immed_double_const (lv, hv, VOIDmode);
+ return immed_double_int_const (v, VOIDmode);
}
return GEN_INT (INTVAL (x) + c);
case CONST_DOUBLE:
{
- unsigned HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
- HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
- unsigned HOST_WIDE_INT l2 = c;
- HOST_WIDE_INT h2 = c < 0 ? -1 : 0;
- unsigned HOST_WIDE_INT lv;
- HOST_WIDE_INT hv;
-
- if (add_double_with_sign (l1, h1, l2, h2, &lv, &hv, false))
+ double_int di_x = double_int::from_pair (CONST_DOUBLE_HIGH (x),
+ CONST_DOUBLE_LOW (x));
+ double_int di_c = double_int::from_shwi (c);
+
+ bool overflow;
+ double_int v = di_x.add_with_sign (di_c, false, &overflow);
+ if (overflow)
/* Sorry, we have no way to represent overflows this wide.
To fix, add constant support wider than CONST_DOUBLE. */
gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
- return immed_double_const (lv, hv, VOIDmode);
+ return immed_double_int_const (v, VOIDmode);
}
case MEM:
diff --git a/gcc/expmed.c b/gcc/expmed.c
index cde9246..767834e 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -3392,12 +3392,9 @@ choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
unsigned HOST_WIDE_INT *multiplier_ptr,
int *post_shift_ptr, int *lgup_ptr)
{
- HOST_WIDE_INT mhigh_hi, mlow_hi;
- unsigned HOST_WIDE_INT mhigh_lo, mlow_lo;
+ double_int mhigh, mlow;
int lgup, post_shift;
int pow, pow2;
- unsigned HOST_WIDE_INT nl, dummy1;
- HOST_WIDE_INT nh, dummy2;
/* lgup = ceil(log2(divisor)); */
lgup = ceil_log2 (d);
@@ -3413,32 +3410,17 @@ choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
gcc_assert (pow != HOST_BITS_PER_DOUBLE_INT);
/* mlow = 2^(N + lgup)/d */
- if (pow >= HOST_BITS_PER_WIDE_INT)
- {
- nh = (HOST_WIDE_INT) 1 << (pow - HOST_BITS_PER_WIDE_INT);
- nl = 0;
- }
- else
- {
- nh = 0;
- nl = (unsigned HOST_WIDE_INT) 1 << pow;
- }
- div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
- &mlow_lo, &mlow_hi, &dummy1, &dummy2);
+ double_int val = double_int_zero.set_bit (pow);
+ mlow = val.div (double_int::from_uhwi (d), true, TRUNC_DIV_EXPR);
- /* mhigh = (2^(N + lgup) + 2^N + lgup - precision)/d */
- if (pow2 >= HOST_BITS_PER_WIDE_INT)
- nh |= (HOST_WIDE_INT) 1 << (pow2 - HOST_BITS_PER_WIDE_INT);
- else
- nl |= (unsigned HOST_WIDE_INT) 1 << pow2;
- div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
- &mhigh_lo, &mhigh_hi, &dummy1, &dummy2);
+ /* mhigh = (2^(N + lgup) + 2^(N + lgup - precision))/d */
+ val |= double_int_zero.set_bit (pow2);
+ mhigh = val.div (double_int::from_uhwi (d), true, TRUNC_DIV_EXPR);
- gcc_assert (!mhigh_hi || nh - d < d);
- gcc_assert (mhigh_hi <= 1 && mlow_hi <= 1);
+ gcc_assert (!mhigh.high || val.high - d < d);
+ gcc_assert (mhigh.high <= 1 && mlow.high <= 1);
/* Assert that mlow < mhigh. */
- gcc_assert (mlow_hi < mhigh_hi
- || (mlow_hi == mhigh_hi && mlow_lo < mhigh_lo));
+ gcc_assert (mlow.ult (mhigh));
/* If precision == N, then mlow, mhigh exceed 2^N
(but they do not exceed 2^(N+1)). */
@@ -3446,15 +3428,14 @@ choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
/* Reduce to lowest terms. */
for (post_shift = lgup; post_shift > 0; post_shift--)
{
- unsigned HOST_WIDE_INT ml_lo = (mlow_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mlow_lo >> 1);
- unsigned HOST_WIDE_INT mh_lo = (mhigh_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mhigh_lo >> 1);
+ int shft = HOST_BITS_PER_WIDE_INT - 1;
+ unsigned HOST_WIDE_INT ml_lo = (mlow.high << shft) | (mlow.low >> 1);
+ unsigned HOST_WIDE_INT mh_lo = (mhigh.high << shft) | (mhigh.low >> 1);
if (ml_lo >= mh_lo)
break;
- mlow_hi = 0;
- mlow_lo = ml_lo;
- mhigh_hi = 0;
- mhigh_lo = mh_lo;
+ mlow = double_int::from_uhwi (ml_lo);
+ mhigh = double_int::from_uhwi (mh_lo);
}
*post_shift_ptr = post_shift;
@@ -3462,13 +3443,13 @@ choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
if (n < HOST_BITS_PER_WIDE_INT)
{
unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT) 1 << n) - 1;
- *multiplier_ptr = mhigh_lo & mask;
- return mhigh_lo >= mask;
+ *multiplier_ptr = mhigh.low & mask;
+ return mhigh.low >= mask;
}
else
{
- *multiplier_ptr = mhigh_lo;
- return mhigh_hi;
+ *multiplier_ptr = mhigh.low;
+ return mhigh.high;
}
}
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 223dc68..3197cef 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -165,17 +165,6 @@ protected_set_expr_location_unshare (tree x, location_t loc)
}
return x;
}
-
-
-/* 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
- addition.
-
- Overflow occurs if A and B have the same sign, but A and SUM differ in
- sign. Use `^' to test whether signs differ, and `< 0' to isolate the
- sign. */
-#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
/* If ARG2 divides ARG1 with zero remainder, carries out the division
of type CODE and returns the quotient.
@@ -982,13 +971,7 @@ int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
break;
case MINUS_EXPR:
-/* FIXME(crowl) Remove this code if the replacment works.
- neg_double (op2.low, op2.high, &res.low, &res.high);
- add_double (op1.low, op1.high, res.low, res.high,
- &res.low, &res.high);
- overflow = OVERFLOW_SUM_SIGN (res.high, op2.high, op1.high);
-*/
- res = op1.add_with_sign (-op2, false, &overflow);
+ res = op1.sub_with_overflow (op2, &overflow);
break;
case MULT_EXPR:
@@ -1035,10 +1018,7 @@ int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
res = double_int_one;
break;
}
- overflow = div_and_round_double (code, uns,
- op1.low, op1.high, op2.low, op2.high,
- &res.low, &res.high,
- &tmp.low, &tmp.high);
+ res = op1.divmod_with_overflow (op2, uns, code, &tmp, &overflow);
break;
case TRUNC_MOD_EXPR:
@@ -1060,10 +1040,7 @@ int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
case ROUND_MOD_EXPR:
if (op2.is_zero ())
return NULL_TREE;
- overflow = div_and_round_double (code, uns,
- op1.low, op1.high, op2.low, op2.high,
- &tmp.low, &tmp.high,
- &res.low, &res.high);
+ tmp = op1.divmod_with_overflow (op2, uns, code, &res, &overflow);
break;
case MIN_EXPR:
@@ -6290,15 +6267,12 @@ fold_div_compare (location_t loc,
double_int val;
bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
bool neg_overflow;
- int overflow;
+ bool overflow;
/* We have to do this the hard way to detect unsigned overflow.
prod = int_const_binop (MULT_EXPR, arg01, arg1); */
- overflow = mul_double_with_sign (TREE_INT_CST_LOW (arg01),
- TREE_INT_CST_HIGH (arg01),
- TREE_INT_CST_LOW (arg1),
- TREE_INT_CST_HIGH (arg1),
- &val.low, &val.high, unsigned_p);
+ val = TREE_INT_CST (arg01)
+ .mul_with_sign (TREE_INT_CST (arg1), unsigned_p, &overflow);
prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow);
neg_overflow = false;
@@ -6309,11 +6283,8 @@ fold_div_compare (location_t loc,
lo = prod;
/* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp). */
- overflow = add_double_with_sign (TREE_INT_CST_LOW (prod),
- TREE_INT_CST_HIGH (prod),
- TREE_INT_CST_LOW (tmp),
- TREE_INT_CST_HIGH (tmp),
- &val.low, &val.high, unsigned_p);
+ val = TREE_INT_CST (prod)
+ .add_with_sign (TREE_INT_CST (tmp), unsigned_p, &overflow);
hi = force_fit_type_double (TREE_TYPE (arg00), val,
-1, overflow | TREE_OVERFLOW (prod));
}
@@ -8691,8 +8662,7 @@ maybe_canonicalize_comparison (location_t loc, enum tree_code code, tree type,
static bool
pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
{
- unsigned HOST_WIDE_INT offset_low, total_low;
- HOST_WIDE_INT size, offset_high, total_high;
+ double_int di_offset, total;
if (!POINTER_TYPE_P (TREE_TYPE (base)))
return true;
@@ -8701,28 +8671,22 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
return true;
if (offset == NULL_TREE)
- {
- offset_low = 0;
- offset_high = 0;
- }
+ di_offset = double_int_zero;
else if (TREE_CODE (offset) != INTEGER_CST || TREE_OVERFLOW (offset))
return true;
else
- {
- offset_low = TREE_INT_CST_LOW (offset);
- offset_high = TREE_INT_CST_HIGH (offset);
- }
+ di_offset = TREE_INT_CST (offset);
- if (add_double_with_sign (offset_low, offset_high,
- bitpos / BITS_PER_UNIT, 0,
- &total_low, &total_high,
- true))
+ bool overflow;
+ double_int units = double_int::from_uhwi (bitpos / BITS_PER_UNIT);
+ total = di_offset.add_with_sign (units, true, &overflow);
+ if (overflow)
return true;
- if (total_high != 0)
+ if (total.high != 0)
return true;
- size = int_size_in_bytes (TREE_TYPE (TREE_TYPE (base)));
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (TREE_TYPE (base)));
if (size <= 0)
return true;
@@ -8737,7 +8701,7 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
size = base_size;
}
- return total_low > (unsigned HOST_WIDE_INT) size;
+ return total.low > (unsigned HOST_WIDE_INT) size;
}
/* Subroutine of fold_binary. This routine performs all of the
@@ -15938,8 +15902,8 @@ fold_negate_const (tree arg0, tree type)
case INTEGER_CST:
{
double_int val = tree_to_double_int (arg0);
- int overflow = neg_double (val.low, val.high, &val.low, &val.high);
-
+ bool overflow;
+ val = val.neg_with_overflow (&overflow);
t = force_fit_type_double (type, val, 1,
(overflow | TREE_OVERFLOW (arg0))
&& !TYPE_UNSIGNED (type));
@@ -15996,9 +15960,8 @@ fold_abs_const (tree arg0, tree type)
its negation. */
else
{
- int overflow;
-
- overflow = neg_double (val.low, val.high, &val.low, &val.high);
+ bool overflow;
+ val = val.neg_with_overflow (&overflow);
t = force_fit_type_double (type, val, -1,
overflow | TREE_OVERFLOW (arg0));
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 1be83d4..d6bfcf9 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,8 @@
+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.
+
2012-09-23 Tobias Burnus <burnus@net-b.de>
* parse.c (parse_derived): Don't set attr.alloc_comp
diff --git a/gcc/fortran/target-memory.c b/gcc/fortran/target-memory.c
index 7a55dcd..aec7fa2 100644
--- a/gcc/fortran/target-memory.c
+++ b/gcc/fortran/target-memory.c
@@ -404,8 +404,7 @@ gfc_interpret_logical (int kind, unsigned char *buffer, size_t buffer_size,
{
tree t = native_interpret_expr (gfc_get_logical_type (kind), buffer,
buffer_size);
- *logical = double_int_zero_p (tree_to_double_int (t))
- ? 0 : 1;
+ *logical = tree_to_double_int (t).is_zero () ? 0 : 1;
return size_logical (kind);
}
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 177d286..319c361 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1667,10 +1667,10 @@ gfc_conv_cst_int_power (gfc_se * se, tree lhs, tree rhs)
/* If exponent is too large, we won't expand it anyway, so don't bother
with large integer values. */
- if (!double_int_fits_in_shwi_p (TREE_INT_CST (rhs)))
+ if (!TREE_INT_CST (rhs).fits_shwi ())
return 0;
- m = double_int_to_shwi (TREE_INT_CST (rhs));
+ m = TREE_INT_CST (rhs).to_shwi ();
/* There's no ABS for HOST_WIDE_INT, so here we go. It also takes care
of the asymmetric range of the integer type. */
n = (unsigned HOST_WIDE_INT) (m < 0 ? -m : m);
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 8fd18aa..96c9df9 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,10 @@
+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.
+
2012-07-30 Laurynas Biveinis <laurynas.biveinis@gmail.com>
* jcf.h (CPool): Use the "atomic" GTY option for the tags field.
diff --git a/gcc/java/boehm.c b/gcc/java/boehm.c
index 07dfb61..0fa8964 100644
--- a/gcc/java/boehm.c
+++ b/gcc/java/boehm.c
@@ -108,7 +108,7 @@ mark_reference_fields (tree field,
bits for all words in the record. This is conservative, but the
size_words != 1 case is impossible in regular java code. */
for (i = 0; i < size_words; ++i)
- *mask = double_int_setbit (*mask, ubit - count - i - 1);
+ *mask = (*mask).set_bit (ubit - count - i - 1);
if (count >= ubit - 2)
*pointer_after_end = 1;
@@ -200,7 +200,7 @@ get_boehm_type_descriptor (tree type)
while (last_set_index)
{
if ((last_set_index & 1))
- mask = double_int_setbit (mask, log2_size + count);
+ mask = mask.set_bit (log2_size + count);
last_set_index >>= 1;
++count;
}
@@ -209,7 +209,7 @@ get_boehm_type_descriptor (tree type)
else if (! pointer_after_end)
{
/* Bottom two bits for bitmap mark type are 01. */
- mask = double_int_setbit (mask, 0);
+ mask = mask.set_bit (0);
value = double_int_to_tree (value_type, mask);
}
else
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index e22b0fd..30048fd 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -617,7 +617,7 @@ java_init_decl_processing (void)
decimal_int_max = build_int_cstu (unsigned_int_type_node, 0x80000000);
decimal_long_max
= double_int_to_tree (unsigned_long_type_node,
- double_int_setbit (double_int_zero, 64));
+ double_int_zero.set_bit (64));
long_zero_node = build_int_cst (long_type_node, 0);
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index c799676..92f032cb 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -1043,9 +1043,9 @@ get_constant (JCF *jcf, int index)
double_int val;
num = JPOOL_UINT (jcf, index);
- val = double_int_lshift (uhwi_to_double_int (num), 32, 64, false);
+ val = double_int::from_uhwi (num).llshift (32, 64);
num = JPOOL_UINT (jcf, index + 1);
- val = double_int_ior (val, uhwi_to_double_int (num));
+ val |= double_int::from_uhwi (num);
value = double_int_to_tree (long_type_node, val);
break;
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 9ed98e6..97a9330 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1525,109 +1525,117 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
else if (width <= HOST_BITS_PER_DOUBLE_INT
&& (CONST_DOUBLE_AS_INT_P (op) || CONST_INT_P (op)))
{
- unsigned HOST_WIDE_INT l1, lv;
- HOST_WIDE_INT h1, hv;
+ double_int first, value;
if (CONST_DOUBLE_AS_INT_P (op))
- l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op);
+ first = double_int::from_pair (CONST_DOUBLE_HIGH (op),
+ CONST_DOUBLE_LOW (op));
else
- l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1);
+ first = double_int::from_shwi (INTVAL (op));
switch (code)
{
case NOT:
- lv = ~ l1;
- hv = ~ h1;
+ value = ~first;
break;
case NEG:
- neg_double (l1, h1, &lv, &hv);
+ value = -first;
break;
case ABS:
- if (h1 < 0)
- neg_double (l1, h1, &lv, &hv);
+ if (first.is_negative ())
+ value = -first;
else
- lv = l1, hv = h1;
+ value = first;
break;
case FFS:
- hv = 0;
- if (l1 != 0)
- lv = ffs_hwi (l1);
- else if (h1 != 0)
- lv = HOST_BITS_PER_WIDE_INT + ffs_hwi (h1);
+ value.high = 0;
+ if (first.low != 0)
+ value.low = ffs_hwi (first.low);
+ else if (first.high != 0)
+ value.low = HOST_BITS_PER_WIDE_INT + ffs_hwi (first.high);
else
- lv = 0;
+ value.low = 0;
break;
case CLZ:
- hv = 0;
- if (h1 != 0)
- lv = GET_MODE_PRECISION (mode) - floor_log2 (h1) - 1
- - HOST_BITS_PER_WIDE_INT;
- else if (l1 != 0)
- lv = GET_MODE_PRECISION (mode) - floor_log2 (l1) - 1;
- else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv))
- lv = GET_MODE_PRECISION (mode);
+ value.high = 0;
+ if (first.high != 0)
+ value.low = GET_MODE_PRECISION (mode) - floor_log2 (first.high) - 1
+ - HOST_BITS_PER_WIDE_INT;
+ else if (first.low != 0)
+ value.low = GET_MODE_PRECISION (mode) - floor_log2 (first.low) - 1;
+ else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, value.low))
+ value.low = GET_MODE_PRECISION (mode);
break;
case CTZ:
- hv = 0;
- if (l1 != 0)
- lv = ctz_hwi (l1);
- else if (h1 != 0)
- lv = HOST_BITS_PER_WIDE_INT + ctz_hwi (h1);
- else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv))
- lv = GET_MODE_PRECISION (mode);
+ value.high = 0;
+ if (first.low != 0)
+ value.low = ctz_hwi (first.low);
+ else if (first.high != 0)
+ value.low = HOST_BITS_PER_WIDE_INT + ctz_hwi (first.high);
+ else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, value.low))
+ value.low = GET_MODE_PRECISION (mode);
break;
case POPCOUNT:
- hv = 0;
- lv = 0;
- while (l1)
- lv++, l1 &= l1 - 1;
- while (h1)
- lv++, h1 &= h1 - 1;
+ value = double_int_zero;
+ while (first.low)
+ {
+ value.low++;
+ first.low &= first.low - 1;
+ }
+ while (first.high)
+ {
+ value.low++;
+ first.high &= first.high - 1;
+ }
break;
case PARITY:
- hv = 0;
- lv = 0;
- while (l1)
- lv++, l1 &= l1 - 1;
- while (h1)
- lv++, h1 &= h1 - 1;
- lv &= 1;
+ value = double_int_zero;
+ while (first.low)
+ {
+ value.low++;
+ first.low &= first.low - 1;
+ }
+ while (first.high)
+ {
+ value.low++;
+ first.high &= first.high - 1;
+ }
+ value.low &= 1;
break;
case BSWAP:
{
unsigned int s;
- hv = 0;
- lv = 0;
+ value = double_int_zero;
for (s = 0; s < width; s += 8)
{
unsigned int d = width - s - 8;
unsigned HOST_WIDE_INT byte;
if (s < HOST_BITS_PER_WIDE_INT)
- byte = (l1 >> s) & 0xff;
+ byte = (first.low >> s) & 0xff;
else
- byte = (h1 >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
+ byte = (first.high >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
if (d < HOST_BITS_PER_WIDE_INT)
- lv |= byte << d;
+ value.low |= byte << d;
else
- hv |= byte << (d - HOST_BITS_PER_WIDE_INT);
+ value.high |= byte << (d - HOST_BITS_PER_WIDE_INT);
}
}
break;
case TRUNCATE:
/* This is just a change-of-mode, so do nothing. */
- lv = l1, hv = h1;
+ value = first;
break;
case ZERO_EXTEND:
@@ -1636,8 +1644,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
if (op_width > HOST_BITS_PER_WIDE_INT)
return 0;
- hv = 0;
- lv = l1 & GET_MODE_MASK (op_mode);
+ value = double_int::from_uhwi (first.low & GET_MODE_MASK (op_mode));
break;
case SIGN_EXTEND:
@@ -1646,11 +1653,11 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
return 0;
else
{
- lv = l1 & GET_MODE_MASK (op_mode);
- if (val_signbit_known_set_p (op_mode, lv))
- lv |= ~GET_MODE_MASK (op_mode);
+ value.low = first.low & GET_MODE_MASK (op_mode);
+ if (val_signbit_known_set_p (op_mode, value.low))
+ value.low |= ~GET_MODE_MASK (op_mode);
- hv = HWI_SIGN_EXTEND (lv);
+ value.high = HWI_SIGN_EXTEND (value.low);
}
break;
@@ -1661,7 +1668,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
return 0;
}
- return immed_double_const (lv, hv, mode);
+ return immed_double_int_const (value, mode);
}
else if (CONST_DOUBLE_AS_FLOAT_P (op)
@@ -3578,6 +3585,7 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
&& (CONST_DOUBLE_AS_INT_P (op1) || CONST_INT_P (op1)))
{
double_int o0, o1, res, tmp;
+ bool overflow;
o0 = rtx_to_double_int (op0);
o1 = rtx_to_double_int (op1);
@@ -3599,34 +3607,30 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
break;
case DIV:
- if (div_and_round_double (TRUNC_DIV_EXPR, 0,
- o0.low, o0.high, o1.low, o1.high,
- &res.low, &res.high,
- &tmp.low, &tmp.high))
+ res = o0.divmod_with_overflow (o1, false, TRUNC_DIV_EXPR,
+ &tmp, &overflow);
+ if (overflow)
return 0;
break;
case MOD:
- if (div_and_round_double (TRUNC_DIV_EXPR, 0,
- o0.low, o0.high, o1.low, o1.high,
- &tmp.low, &tmp.high,
- &res.low, &res.high))
+ tmp = o0.divmod_with_overflow (o1, false, TRUNC_DIV_EXPR,
+ &res, &overflow);
+ if (overflow)
return 0;
break;
case UDIV:
- if (div_and_round_double (TRUNC_DIV_EXPR, 1,
- o0.low, o0.high, o1.low, o1.high,
- &res.low, &res.high,
- &tmp.low, &tmp.high))
+ res = o0.divmod_with_overflow (o1, true, TRUNC_DIV_EXPR,
+ &tmp, &overflow);
+ if (overflow)
return 0;
break;
case UMOD:
- if (div_and_round_double (TRUNC_DIV_EXPR, 1,
- o0.low, o0.high, o1.low, o1.high,
- &tmp.low, &tmp.high,
- &res.low, &res.high))
+ tmp = o0.divmod_with_overflow (o1, true, TRUNC_DIV_EXPR,
+ &res, &overflow);
+ if (overflow)
return 0;
break;
diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
index 9159992..309d437 100644
--- a/gcc/tree-chrec.c
+++ b/gcc/tree-chrec.c
@@ -461,8 +461,8 @@ chrec_fold_multiply (tree type,
static tree
tree_fold_binomial (tree type, tree n, unsigned int k)
{
- unsigned HOST_WIDE_INT lidx, lnum, ldenom, lres, ldum;
- HOST_WIDE_INT hidx, hnum, hdenom, hres, hdum;
+ double_int num, denom, idx, di_res;
+ bool overflow;
unsigned int i;
tree res;
@@ -472,59 +472,41 @@ tree_fold_binomial (tree type, tree n, unsigned int k)
if (k == 1)
return fold_convert (type, n);
+ /* Numerator = n. */
+ num = TREE_INT_CST (n);
+
/* Check that k <= n. */
- if (TREE_INT_CST_HIGH (n) == 0
- && TREE_INT_CST_LOW (n) < k)
+ if (num.ult (double_int::from_uhwi (k)))
return NULL_TREE;
- /* Numerator = n. */
- lnum = TREE_INT_CST_LOW (n);
- hnum = TREE_INT_CST_HIGH (n);
-
/* Denominator = 2. */
- ldenom = 2;
- hdenom = 0;
+ denom = double_int::from_uhwi (2);
/* Index = Numerator-1. */
- if (lnum == 0)
- {
- hidx = hnum - 1;
- lidx = ~ (unsigned HOST_WIDE_INT) 0;
- }
- else
- {
- hidx = hnum;
- lidx = lnum - 1;
- }
+ idx = num - double_int_one;
/* Numerator = Numerator*Index = n*(n-1). */
- if (mul_double (lnum, hnum, lidx, hidx, &lnum, &hnum))
+ num = num.mul_with_sign (idx, false, &overflow);
+ if (overflow)
return NULL_TREE;
for (i = 3; i <= k; i++)
{
/* Index--. */
- if (lidx == 0)
- {
- hidx--;
- lidx = ~ (unsigned HOST_WIDE_INT) 0;
- }
- else
- lidx--;
+ --idx;
/* Numerator *= Index. */
- if (mul_double (lnum, hnum, lidx, hidx, &lnum, &hnum))
+ num = num.mul_with_sign (idx, false, &overflow);
+ if (overflow)
return NULL_TREE;
/* Denominator *= i. */
- mul_double (ldenom, hdenom, i, 0, &ldenom, &hdenom);
+ denom *= double_int::from_uhwi (i);
}
/* Result = Numerator / Denominator. */
- div_and_round_double (EXACT_DIV_EXPR, 1, lnum, hnum, ldenom, hdenom,
- &lres, &hres, &ldum, &hdum);
-
- res = build_int_cst_wide (type, lres, hres);
+ di_res = num.div (denom, true, EXACT_DIV_EXPR);
+ res = build_int_cst_wide (type, di_res.low, di_res.high);
return int_fits_type_p (res, type) ? res : NULL_TREE;
}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 34f1d1a..a84c4b9 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -2478,7 +2478,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
if (tmin.cmp (tmax, uns) < 0)
covers = true;
tmax = tem + double_int_minus_one;
- if (double_int_cmp (tmax, tem, uns) > 0)
+ if (tmax.cmp (tem, uns) > 0)
covers = true;
/* If the anti-range would cover nothing, drop to varying.
Likewise if the anti-range bounds are outside of the
@@ -2632,37 +2632,26 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
}
uns = uns0 & uns1;
- mul_double_wide_with_sign (min0.low, min0.high,
- min1.low, min1.high,
- &prod0l.low, &prod0l.high,
- &prod0h.low, &prod0h.high, true);
+ bool overflow;
+ prod0l = min0.wide_mul_with_sign (min1, true, &prod0h, &overflow);
if (!uns0 && min0.is_negative ())
prod0h -= min1;
if (!uns1 && min1.is_negative ())
prod0h -= min0;
- mul_double_wide_with_sign (min0.low, min0.high,
- max1.low, max1.high,
- &prod1l.low, &prod1l.high,
- &prod1h.low, &prod1h.high, true);
+ prod1l = min0.wide_mul_with_sign (max1, true, &prod1h, &overflow);
if (!uns0 && min0.is_negative ())
prod1h -= max1;
if (!uns1 && max1.is_negative ())
prod1h -= min0;
- mul_double_wide_with_sign (max0.low, max0.high,
- min1.low, min1.high,
- &prod2l.low, &prod2l.high,
- &prod2h.low, &prod2h.high, true);
+ prod2l = max0.wide_mul_with_sign (min1, true, &prod2h, &overflow);
if (!uns0 && max0.is_negative ())
prod2h -= min1;
if (!uns1 && min1.is_negative ())
prod2h -= max0;
- mul_double_wide_with_sign (max0.low, max0.high,
- max1.low, max1.high,
- &prod3l.low, &prod3l.high,
- &prod3h.low, &prod3h.high, true);
+ prod3l = max0.wide_mul_with_sign (max1, true, &prod3h, &overflow);
if (!uns0 && max0.is_negative ())
prod3h -= max1;
if (!uns1 && max1.is_negative ())