This fixes a regression introduced in GCC 4.2 after which we no longer fold (unsigned) (X /[ex] 4) * 4 to (unsigned) X.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2013-10-21 Richard Biener <rguent...@suse.de> PR middle-end/58742 * fold-const.c (fold_binary_loc): Fold ((T) (X /[ex] C)) * C to (T) X for sign-changing conversions (or no conversion). * c-c++-common/fold-divmul-1.c: New testcase. Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 203885) --- gcc/fold-const.c (working copy) *************** fold_binary_loc (location_t loc, *** 11002,11007 **** --- 11002,11014 ---- fold_build2_loc (loc, MULT_EXPR, type, build_int_cst (type, 2) , arg1)); + /* ((T) (X /[ex] C)) * C cancels out if the conversion is + sign-changing only. */ + if (TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (arg0) == EXACT_DIV_EXPR + && operand_equal_p (arg1, TREE_OPERAND (arg0, 1), 0)) + return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); + strict_overflow_p = false; if (TREE_CODE (arg1) == INTEGER_CST && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE, Index: gcc/testsuite/c-c++-common/fold-divmul-1.c =================================================================== *** gcc/testsuite/c-c++-common/fold-divmul-1.c (revision 0) --- gcc/testsuite/c-c++-common/fold-divmul-1.c (working copy) *************** *** 0 **** --- 1,11 ---- + /* { dg-do compile } */ + /* { dg-options "-fdump-tree-original" } */ + + int * + fx (int *b, int *e) + { + return b + (e - b); + } + + /* { dg-final { scan-tree-dump-not "/\\\[ex\\\]" "original" } } */ + /* { dg-final { cleanup-tree-dump "original" } } */