diff options
author | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 1994-03-25 21:12:56 +0000 |
---|---|---|
committer | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 1994-03-25 21:12:56 +0000 |
commit | ae9613cf1379b7c541608d8018deeaf2ea395735 (patch) | |
tree | c032a4ada6c674eb4ac98127471c3796a8a25ab1 /gcc/fold-const.c | |
parent | 7a412f78602f2c16c30b2f0157049865b7e2980f (diff) | |
download | ppe42-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.c | 44 |
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. */ |