From: Richard Kenner Date: Tue, 12 Jul 1994 16:39:17 +0000 (-0400) Subject: (fold, case MULT_EXPR): If arg is an unsigned CEIL_DIV_EXPR, convert X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=78221d63e7596bac0d05b905219f01e0b9daab6d;p=gcc.git (fold, case MULT_EXPR): If arg is an unsigned CEIL_DIV_EXPR, convert to TRUNC_DIV_EXPR of a PLUS_EXPR in some cases. From-SVN: r7744 --- diff --git a/gcc/fold-const.c b/gcc/fold-const.c index fc611902aa4..15509a3f07a 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3751,6 +3751,24 @@ fold (expr) && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)) return TREE_OPERAND (arg0, 0); + /* If we have ((A / C1) * C2) with C1 and C2 constant, + C2 >= C1, and the division an unsigned CEIL_DIV_EXPR, + we know that the addition that's part of the CEIL_DIV_EXPR + cannot overflow while the generic CEIL_DIV_EXPR does not. + So convert it into a TRUNC_DIV_EXPR of an add. */ + if (TREE_CODE (arg0) == CEIL_DIV_EXPR && TREE_UNSIGNED (type) + && TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST + && ! tree_int_cst_lt (arg1, TREE_OPERAND (arg0, 1))) + return + build (MULT_EXPR, type, + build (TRUNC_DIV_EXPR, type, + build (PLUS_EXPR, type, + TREE_OPERAND (TREE_OPERAND (arg0, 0), 0)), + const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 1), + integer_one_node, 0)), + arg1); + /* (a * (1 << b)) is (a << b) */ if (TREE_CODE (arg1) == LSHIFT_EXPR && integer_onep (TREE_OPERAND (arg1, 0)))