This fixes PR53501, fold_plusminus_mult_expr does not expect that operands have a sign-conversion stripped. So don't call it with such arguments.
Bootstrap and regtest pending on x86_64-unknown-linux-gnu. Richard. 2012-05-30 Richard Guenther <rguent...@suse.de> PR middle-end/53501 * fold-const.c (fold_binary_loc): Make sure to call fold_plusminus_mult_expr with the original sign of operands. * gcc.dg/torture/pr53501.c: New testcase. Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 188004) --- gcc/fold-const.c (working copy) *************** fold_binary_loc (location_t loc, *** 10045,10056 **** /* 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) && !TYPE_SATURATING (type) && (!FLOAT_TYPE_P (type) || flag_associative_math)) { ! tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1); if (tem) return tem; } --- 10045,10056 ---- /* 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 (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, op0, op1); if (tem) return tem; } *************** fold_binary_loc (location_t loc, *** 10668,10679 **** /* 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) && !TYPE_SATURATING (type) && (!FLOAT_TYPE_P (type) || flag_associative_math)) { ! tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1); if (tem) return tem; } --- 10668,10679 ---- /* 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 (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, op0, op1); if (tem) return tem; } Index: gcc/testsuite/gcc.dg/torture/pr53501.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr53501.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr53501.c (revision 0) *************** *** 0 **** --- 1,22 ---- + /* { dg-do run } */ + + extern void abort (void); + + int e[100], n, here; + + void __attribute__((noinline)) + foo(void) + { + int i, k = 0; + for (i = 0; i < n; ++i) { e[k] = 10; ++k; e[k] = 10; ++k; } + for (i = 0; i < k; ++i) here = 1; + if (here != 1) + abort (); + } + + int main(void) + { + n = 10; + foo(); + return 0; + }