diff options
author | Eric Botcazou <ebotcazou@libertysurf.fr> | 2005-06-16 23:25:00 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2005-06-16 21:25:00 +0000 |
commit | 0d22e81f866c4899b4481f2052833cd031a778d1 (patch) | |
tree | 84c25a09eddd7ede8024c7825f30c9798ec849d4 /gcc/tree-vrp.c | |
parent | 9b9c745ee35407c173875e5a15d8e98a242330a6 (diff) | |
download | gcc-0d22e81f866c4899b4481f2052833cd031a778d1.zip gcc-0d22e81f866c4899b4481f2052833cd031a778d1.tar.gz gcc-0d22e81f866c4899b4481f2052833cd031a778d1.tar.bz2 |
re PR tree-optimization/22018 (VRP miscompiles multiply)
PR tree-optimization/22018
* tree-vrp.c (vrp_int_const_binop): Overhaul handling of overflow.
From-SVN: r101097
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index c0d0514..e040f41 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -986,30 +986,41 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) res = int_const_binop (code, val1, val2, 0); /* If the operation overflowed but neither VAL1 nor VAL2 are - overflown, return -INF or +INF depending on whether VAL1 CODE - VAL2 is a growing function or not. */ + overflown, return -INF or +INF depending on the operation + and the combination of signs of the operands. */ if (TREE_OVERFLOW (res) && !TREE_OVERFLOW (val1) && !TREE_OVERFLOW (val2)) { - bool grows = false; int sgn1 = tree_int_cst_sgn (val1); int sgn2 = tree_int_cst_sgn (val2); - /* Determine whether VAL1 CODE VAL2 yields a growing value. - Notice that we only need to handle the restricted set of - operations handled by extract_range_from_binary_expr: - - VAL1 + VAL2 grows if VAL2 is >= 0. - VAL1 * VAL2 grows if both VAL1 and VAL2 have the same sign. - VAL1 - VAL2 grows if VAL2 is < 0 (because it becomes an addition). - */ - if ((code == PLUS_EXPR && sgn2 >= 0) - || (code == MULT_EXPR && sgn1 == sgn2) - || (code == MINUS_EXPR && sgn2 < 0)) - grows = true; - - if (grows) + /* Notice that we only need to handle the restricted set of + operations handled by extract_range_from_binary_expr. + Among them, only multiplication, addition and subtraction + can yield overflow without overflown operands because we + are working with integral types only... except in the + case VAL1 = -INF and VAL2 = -1 which overflows to +INF + for division too. */ + + /* For multiplication, the sign of the overflow is given + by the comparison of the signs of the operands. */ + if ((code == MULT_EXPR && sgn1 == sgn2) + /* For addition, the operands must be of the same sign + to yield an overflow. Its sign is therefore that + of one of the operands, for example the first. */ + || (code == PLUS_EXPR && sgn1 > 0) + /* For subtraction, the operands must be of different + signs to yield an overflow. Its sign is therefore + that of the first operand or the opposite of that + of the second operand. */ + || (code == MINUS_EXPR && sgn1 > 0) + /* For division, the only case is -INF / -1 = +INF. */ + || code == TRUNC_DIV_EXPR + || code == FLOOR_DIV_EXPR + || code == CEIL_DIV_EXPR + || code == EXACT_DIV_EXPR + || code == ROUND_DIV_EXPR) return TYPE_MAX_VALUE (TREE_TYPE (res)); else return TYPE_MIN_VALUE (TREE_TYPE (res)); |