summaryrefslogtreecommitdiffstats
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1994-03-25 21:12:56 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1994-03-25 21:12:56 +0000
commitae9613cf1379b7c541608d8018deeaf2ea395735 (patch)
treec032a4ada6c674eb4ac98127471c3796a8a25ab1 /gcc/fold-const.c
parent7a412f78602f2c16c30b2f0157049865b7e2980f (diff)
downloadppe42-gcc-ae9613cf1379b7c541608d8018deeaf2ea395735.tar.gz
ppe42-gcc-ae9613cf1379b7c541608d8018deeaf2ea395735.zip
(fold, case *_DIV_EXPR): Correct result when product of constants
overflows. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@6900 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59da9acd258..e2f5fc498c5 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -4008,30 +4008,44 @@ fold (expr)
tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 1), arg1, 0);
/* If it overflows, the result is +/- 1 or zero, depending on
- the signs of the two constants and the division operation. */
+ the signs of the constants and remaining operand and on which
+ division operation is being performed. */
+
if (TREE_OVERFLOW (tem))
{
+ /* 1 if C1 * C2 is negative (i.e., C1 and C2 have
+ different signs). */
+ int c_neg = ((tree_int_cst_sgn (arg1) < 0)
+ == (tree_int_cst_sgn (TREE_OPERAND (arg0, 1)) < 0));
+
switch (code)
{
case EXACT_DIV_EXPR:
+ /* If this overflowed, it couldn't have been exact. */
+ abort ();
+
case TRUNC_DIV_EXPR:
- tem = integer_zero_node;
- break;
+ return omit_one_operand (type, integer_zero_node,
+ TREE_OPERAND (arg0, 0));
+
case FLOOR_DIV_EXPR:
- /* -1 if signs disagree, else 0. */
- tem = (((tree_int_cst_sgn (TREE_OPERAND (arg0, 1)) < 0)
- != (tree_int_cst_sgn (arg1) < 0))
- ? build_int_2 (-1, -1) : integer_zero_node);
- break;
+ /* -1 or zero, depending on signs of remaining
+ operand and constants. */
+ tem = build (c_neg ? GE_EXPR : LE_EXPR, integer_type_node,
+ TREE_OPERAND (arg0, 0),
+ convert (type, integer_zero_node));
+ return fold (build (NEGATE_EXPR, type,
+ convert (type, fold (tem))));
+
case CEIL_DIV_EXPR:
- /* 1 if signs agree, else 0. */
- tem = (((tree_int_cst_sgn (TREE_OPERAND (arg0, 1)) < 0)
- == (tree_int_cst_sgn (arg1) < 0))
- ? integer_one_node : integer_zero_node);
- break;
+ /* Zero or 1, depending on signs of remaining
+ operand and constants. */
+ tem = build (c_neg ? LE_EXPR : GE_EXPR, integer_type_node,
+ TREE_OPERAND (arg0, 0),
+ convert (type, integer_zero_node));
+
+ return convert (type, fold (tem));
}
-
- return omit_one_operand (type, tem, TREE_OPERAND (arg0, 0));
}
else
/* If no overflow, divide by C1*C2. */
OpenPOWER on IntegriCloud