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;
+ }

Reply via email to