diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2018-07-07 08:49:04 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2018-07-07 08:49:04 +0000 |
commit | 4a669ac35988fa6de5931455fb59c713563bc58b (patch) | |
tree | 9d2011edd9c0f88e911bf1ca42ef0a447245abf3 /gcc/wide-int.cc | |
parent | 962b3564e98b2634a2d001eceb946d8f15f9bfae (diff) | |
download | gcc-4a669ac35988fa6de5931455fb59c713563bc58b.zip gcc-4a669ac35988fa6de5931455fb59c713563bc58b.tar.gz gcc-4a669ac35988fa6de5931455fb59c713563bc58b.tar.bz2 |
tree-vrp.c (vrp_int_const_binop): Change overflow type to overflow_type.
* tree-vrp.c (vrp_int_const_binop): Change overflow type to
overflow_type.
(combine_bound): Use wide-int overflow calculation instead of
rolling our own.
* calls.c (maybe_warn_alloc_args_overflow): Change overflow type to
overflow_type.
* fold-const.c (int_const_binop_2): Same.
(extract_muldiv_1): Same.
(fold_div_compare): Same.
(fold_abs_const): Same.
* match.pd: Same.
* poly-int.h (add): Same.
(sub): Same.
(neg): Same.
(mul): Same.
* predict.c (predict_iv_comparison): Same.
* profile-count.c (slow_safe_scale_64bit): Same.
* simplify-rtx.c (simplify_const_binary_operation): Same.
* tree-chrec.c (tree_fold_binomial): Same.
* tree-data-ref.c (split_constant_offset_1): Same.
* tree-if-conv.c (idx_within_array_bound): Same.
* tree-scalar-evolution.c (iv_can_overflow_p): Same.
* tree-ssa-phiopt.c (minmax_replacement): Same.
* tree-vect-loop.c (is_nonwrapping_integer_induction): Same.
* tree-vect-stmts.c (vect_truncate_gather_scatter_offset): Same.
* vr-values.c (vr_values::adjust_range_with_scev): Same.
* wide-int.cc (wi::add_large): Same.
(wi::mul_internal): Same.
(wi::sub_large): Same.
(wi::divmod_internal): Same.
* wide-int.h: Change overflow type to overflow_type for neg, add,
mul, smul, umul, div_trunc, div_floor, div_ceil, div_round,
mod_trunc, mod_ceil, mod_round, add_large, sub_large,
mul_internal, divmod_internal.
(overflow_type): New enum.
(accumulate_overflow): New.
cp/
* decl.c (build_enumerator): Change overflow type to overflow_type.
* init.c (build_new_1): Same.
From-SVN: r262494
Diffstat (limited to 'gcc/wide-int.cc')
-rw-r--r-- | gcc/wide-int.cc | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc index 8173146..d9e353c 100644 --- a/gcc/wide-int.cc +++ b/gcc/wide-int.cc @@ -1128,7 +1128,7 @@ unsigned int wi::add_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, unsigned int op0len, const HOST_WIDE_INT *op1, unsigned int op1len, unsigned int prec, - signop sgn, bool *overflow) + signop sgn, wi::overflow_type *overflow) { unsigned HOST_WIDE_INT o0 = 0; unsigned HOST_WIDE_INT o1 = 0; @@ -1158,7 +1158,8 @@ wi::add_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, val[len] = mask0 + mask1 + carry; len++; if (overflow) - *overflow = (sgn == UNSIGNED && carry); + *overflow + = (sgn == UNSIGNED && carry) ? wi::OVF_OVERFLOW : wi::OVF_NONE; } else if (overflow) { @@ -1166,7 +1167,17 @@ wi::add_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, if (sgn == SIGNED) { unsigned HOST_WIDE_INT x = (val[len - 1] ^ o0) & (val[len - 1] ^ o1); - *overflow = (HOST_WIDE_INT) (x << shift) < 0; + if ((HOST_WIDE_INT) (x << shift) < 0) + { + if (o0 > (unsigned HOST_WIDE_INT) val[len - 1]) + *overflow = wi::OVF_UNDERFLOW; + else if (o0 < (unsigned HOST_WIDE_INT) val[len - 1]) + *overflow = wi::OVF_OVERFLOW; + else + *overflow = wi::OVF_NONE; + } + else + *overflow = wi::OVF_NONE; } else { @@ -1174,9 +1185,9 @@ wi::add_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, x <<= shift; o0 <<= shift; if (old_carry) - *overflow = (x <= o0); + *overflow = (x <= o0) ? wi::OVF_OVERFLOW : wi::OVF_NONE; else - *overflow = (x < o0); + *overflow = (x < o0) ? wi::OVF_OVERFLOW : wi::OVF_NONE; } } @@ -1264,12 +1275,14 @@ wi_pack (HOST_WIDE_INT *result, made to see if it overflows. Unfortunately there is no better way to check for overflow than to do this. If OVERFLOW is nonnull, record in *OVERFLOW whether the result overflowed. SGN controls - the signedness and is used to check overflow or if HIGH is set. */ + the signedness and is used to check overflow or if HIGH is set. + + NOTE: Overflow type for signed overflow is not yet implemented. */ unsigned int wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val, unsigned int op1len, const HOST_WIDE_INT *op2val, unsigned int op2len, unsigned int prec, signop sgn, - bool *overflow, bool high) + wi::overflow_type *overflow, bool high) { unsigned HOST_WIDE_INT o0, o1, k, t; unsigned int i; @@ -1294,7 +1307,7 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val, just make sure that we never attempt to set it. */ bool needs_overflow = (overflow != 0); if (needs_overflow) - *overflow = false; + *overflow = wi::OVF_NONE; wide_int_ref op1 = wi::storage_ref (op1val, op1len, prec); wide_int_ref op2 = wi::storage_ref (op2val, op2len, prec); @@ -1337,7 +1350,8 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val, unsigned HOST_WIDE_INT upper; umul_ppmm (upper, val[0], op1.ulow (), op2.ulow ()); if (needs_overflow) - *overflow = (upper != 0); + /* Unsigned overflow can only be +OVERFLOW. */ + *overflow = (upper != 0) ? wi::OVF_OVERFLOW : wi::OVF_NONE; if (high) val[0] = upper; return 1; @@ -1394,12 +1408,14 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val, if (sgn == SIGNED) { if ((HOST_WIDE_INT) r != sext_hwi (r, prec)) - *overflow = true; + /* FIXME: Signed overflow type is not implemented yet. */ + *overflow = OVF_UNKNOWN; } else { if ((r >> prec) != 0) - *overflow = true; + /* Unsigned overflow can only be +OVERFLOW. */ + *overflow = OVF_OVERFLOW; } } val[0] = high ? r >> prec : r; @@ -1474,7 +1490,8 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val, for (i = half_blocks_needed; i < half_blocks_needed * 2; i++) if (((HOST_WIDE_INT)(r[i] & mask)) != top) - *overflow = true; + /* FIXME: Signed overflow type is not implemented yet. */ + *overflow = (sgn == UNSIGNED) ? wi::OVF_OVERFLOW : wi::OVF_UNKNOWN; } int r_offset = high ? half_blocks_needed : 0; @@ -1518,7 +1535,7 @@ unsigned int wi::sub_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, unsigned int op0len, const HOST_WIDE_INT *op1, unsigned int op1len, unsigned int prec, - signop sgn, bool *overflow) + signop sgn, wi::overflow_type *overflow) { unsigned HOST_WIDE_INT o0 = 0; unsigned HOST_WIDE_INT o1 = 0; @@ -1552,7 +1569,7 @@ wi::sub_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, val[len] = mask0 - mask1 - borrow; len++; if (overflow) - *overflow = (sgn == UNSIGNED && borrow); + *overflow = (sgn == UNSIGNED && borrow) ? OVF_UNDERFLOW : OVF_NONE; } else if (overflow) { @@ -1560,7 +1577,17 @@ wi::sub_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, if (sgn == SIGNED) { unsigned HOST_WIDE_INT x = (o0 ^ o1) & (val[len - 1] ^ o0); - *overflow = (HOST_WIDE_INT) (x << shift) < 0; + if ((HOST_WIDE_INT) (x << shift) < 0) + { + if (o0 > o1) + *overflow = OVF_UNDERFLOW; + else if (o0 < o1) + *overflow = OVF_OVERFLOW; + else + *overflow = OVF_NONE; + } + else + *overflow = OVF_NONE; } else { @@ -1568,9 +1595,9 @@ wi::sub_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0, x <<= shift; o0 <<= shift; if (old_borrow) - *overflow = (x >= o0); + *overflow = (x >= o0) ? OVF_UNDERFLOW : OVF_NONE; else - *overflow = (x > o0); + *overflow = (x > o0) ? OVF_UNDERFLOW : OVF_NONE; } } @@ -1706,7 +1733,7 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len, unsigned int dividend_len, unsigned int dividend_prec, const HOST_WIDE_INT *divisor_val, unsigned int divisor_len, unsigned int divisor_prec, signop sgn, - bool *oflow) + wi::overflow_type *oflow) { unsigned int dividend_blocks_needed = 2 * BLOCKS_NEEDED (dividend_prec); unsigned int divisor_blocks_needed = 2 * BLOCKS_NEEDED (divisor_prec); @@ -1750,8 +1777,8 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len, *remainder_len = 1; remainder[0] = 0; } - if (oflow != 0) - *oflow = true; + if (oflow) + *oflow = OVF_OVERFLOW; if (quotient) for (unsigned int i = 0; i < dividend_len; ++i) quotient[i] = dividend_val[i]; @@ -1759,7 +1786,7 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len, } if (oflow) - *oflow = false; + *oflow = OVF_NONE; /* Do it on the host if you can. */ if (sgn == SIGNED @@ -2421,30 +2448,30 @@ test_overflow () { int prec = precs[i]; int offset = offsets[j]; - bool overflow; + wi::overflow_type overflow; wide_int sum, diff; sum = wi::add (wi::max_value (prec, UNSIGNED) - offset, 1, UNSIGNED, &overflow); ASSERT_EQ (sum, -offset); - ASSERT_EQ (overflow, offset == 0); + ASSERT_EQ (overflow != wi::OVF_NONE, offset == 0); sum = wi::add (1, wi::max_value (prec, UNSIGNED) - offset, UNSIGNED, &overflow); ASSERT_EQ (sum, -offset); - ASSERT_EQ (overflow, offset == 0); + ASSERT_EQ (overflow != wi::OVF_NONE, offset == 0); diff = wi::sub (wi::max_value (prec, UNSIGNED) - offset, wi::max_value (prec, UNSIGNED), UNSIGNED, &overflow); ASSERT_EQ (diff, -offset); - ASSERT_EQ (overflow, offset != 0); + ASSERT_EQ (overflow != wi::OVF_NONE, offset != 0); diff = wi::sub (wi::max_value (prec, UNSIGNED) - offset, wi::max_value (prec, UNSIGNED) - 1, UNSIGNED, &overflow); ASSERT_EQ (diff, 1 - offset); - ASSERT_EQ (overflow, offset > 1); + ASSERT_EQ (overflow != wi::OVF_NONE, offset > 1); } } |