diff options
author | Richard Biener <rguenther@suse.de> | 2015-10-28 10:01:23 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2015-10-28 10:01:23 +0000 |
commit | 254b22cc79c594756343f645cbcf7163e39cf5b4 (patch) | |
tree | 7ab6a96e8d54ebc23cadb2b7c7cab37e3c07e38a /gcc/fold-const.c | |
parent | af7ff91b2425e201c00333f0343fd7e28297d8dc (diff) | |
download | gcc-254b22cc79c594756343f645cbcf7163e39cf5b4.zip gcc-254b22cc79c594756343f645cbcf7163e39cf5b4.tar.gz gcc-254b22cc79c594756343f645cbcf7163e39cf5b4.tar.bz2 |
re PR middle-end/68067 (Wrong constant folding)
2015-10-28 Richard Biener <rguenther@suse.de>
PR middle-end/68067
* fold-const.c (negate_expr_p): We cannot negate plus or minus
if overflow is not wrapping. Likewise multiplication unless
one operand is constant and not power of two.
(fold_negate_expr): Adjust accordingly.
* gcc.dg/torture/pr68067-1.c: New testcase.
* gcc.dg/torture/pr68067-2.c: Likewise.
From-SVN: r229479
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e8ff1de..61801cb 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -443,7 +443,9 @@ negate_expr_p (tree t) case PLUS_EXPR: if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) - || HONOR_SIGNED_ZEROS (element_mode (type))) + || HONOR_SIGNED_ZEROS (element_mode (type)) + || (INTEGRAL_TYPE_P (type) + && ! TYPE_OVERFLOW_WRAPS (type))) return false; /* -(A + B) -> (-B) - A. */ if (negate_expr_p (TREE_OPERAND (t, 1)) @@ -457,12 +459,23 @@ negate_expr_p (tree t) /* We can't turn -(A-B) into B-A when we honor signed zeros. */ return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) && !HONOR_SIGNED_ZEROS (element_mode (type)) + && (! INTEGRAL_TYPE_P (type) + || TYPE_OVERFLOW_WRAPS (type)) && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)); case MULT_EXPR: - if (TYPE_UNSIGNED (TREE_TYPE (t))) - break; + if (TYPE_UNSIGNED (type)) + break; + /* INT_MIN/n * n doesn't overflow while negating one operand it does + if n is a power of two. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (t)) + && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (t)) + && ! ((TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST + && ! integer_pow2p (TREE_OPERAND (t, 0))) + || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST + && ! integer_pow2p (TREE_OPERAND (t, 1))))) + break; /* Fall through. */ |