aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-12-13 07:50:58 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1994-12-13 07:50:58 -0500
commitae4311830e2a3915fe7c05227ac4a49d960420b7 (patch)
treedff17658f3eb622fa50779555d50fc90b54a0dba /gcc
parentcd8ce14b50e90712ceaabbab45f6fa286675739b (diff)
downloadgcc-ae4311830e2a3915fe7c05227ac4a49d960420b7.zip
gcc-ae4311830e2a3915fe7c05227ac4a49d960420b7.tar.gz
gcc-ae4311830e2a3915fe7c05227ac4a49d960420b7.tar.bz2
(expand_expr, case MINUS_EXPR): Properly handle case when the NEGATE
overflows. From-SVN: r8648
Diffstat (limited to 'gcc')
-rw-r--r--gcc/expr.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 6634811..fc6223e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5239,10 +5239,29 @@ expand_expr (exp, target, tmode, modifier)
/* Convert A - const to A + (-const). */
if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
{
- exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0),
- fold (build1 (NEGATE_EXPR, type,
- TREE_OPERAND (exp, 1))));
- goto plus_expr;
+ tree negated = fold (build1 (NEGATE_EXPR, type,
+ TREE_OPERAND (exp, 1)));
+
+ /* Deal with the case where we can't negate the constant
+ in TYPE. */
+ if (TREE_UNSIGNED (type) || TREE_OVERFLOW (negated))
+ {
+ tree newtype = signed_type (type);
+ tree newop0 = convert (newtype, TREE_OPERAND (exp, 0));
+ tree newop1 = convert (newtype, TREE_OPERAND (exp, 1));
+ tree newneg = fold (build1 (NEGATE_EXPR, newtype, newop1));
+
+ if (! TREE_OVERFLOW (newneg))
+ return expand_expr (convert (type,
+ build (PLUS_EXPR, newtype,
+ newop0, newneg)),
+ target, tmode, modifier);
+ }
+ else
+ {
+ exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), negated);
+ goto plus_expr;
+ }
}
this_optab = sub_optab;
goto binop;