http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53501
--- Comment #3 from Richard Guenther <rguenth at gcc dot gnu.org> 2012-05-30 10:34:50 UTC --- It's my very best friend extract_muldiv that transforms (int)((unsigned int) n.0_26 + 4294967295) * 2 to (int)(((unsigned int) n.0_26 + 2147483647) * 2) It is the folding of (int) (((unsigned int) n.0_26 + 2147483647) * 2) + 2 which is wrong and done by fold_plusminus_mult_expr. Patch: Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 188004) +++ gcc/fold-const.c (working copy) @@ -10045,12 +10045,12 @@ fold_binary_loc (location_t loc, /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the same or one. Make sure type is not saturating. fold_plusminus_mult_expr will re-associate. */ - if ((TREE_CODE (arg0) == MULT_EXPR - || TREE_CODE (arg1) == MULT_EXPR) + if ((TREE_CODE (op0) == MULT_EXPR + || TREE_CODE (op1) == MULT_EXPR) && !TYPE_SATURATING (type) && (!FLOAT_TYPE_P (type) || flag_associative_math)) { - tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1); + tree tem = fold_plusminus_mult_expr (loc, code, type, op0, op1); if (tem) return tem; } that will leave the expression unsimplified.