summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-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