On Mon, Apr 25, 2016 at 9:21 PM, Marc Glisse <marc.gli...@inria.fr> wrote:
> Hello,
>
> a simple transform to replace a more complicated one in fold-const.c.
>
> This patch breaks the testcase gcc.dg/gomp/loop-1.c. Indeed, the C front-end
> folds too eagerly
>       newrhs = c_fully_fold (newrhs, false, NULL);
> in build_modify_expr, and by the time the OMP code checks that the increment
> in the for loop has the right form, it sees i=i*2 instead of i=i+i. Since
> the original code is apparently illegal, I guess it isn't that bad... The
> C++ front-end seems fine.
>
> Testcase no-strict-overflow-6.c also breaks. ivcanon is clever enough to
> count how many iterations there are before i*=2 makes i negative, which I
> guess would be great with -fwrapv, but I find it a bit suspicious with just
> -fno-strict-overflow. I adjusted the testcase assuming the ivcanon was doing
> the right thing (with -fstrict-overflow we generate an infinite loop
> instead, so it is still testing that).
>
> Bootstrap+regtest on powerpc64le-unknown-linux-gnu.

Ok.  Note that I think

/* (X /[ex] A) * A -> X.  */
(simplify
  (mult (convert? (exact_div @0 @1)) @1)
  /* Look through a sign-changing conversion.  */
  (convert @0))

has a bug as we use operand_equal_p for comparing @1 but
that treats equal but different typed INTEGER_CSTs as equal...

Thus this lacks the tree_nop_conversion_p check.

Thanks,
Richard.

> 2016-04-26  Marc Glisse  <marc.gli...@inria.fr>
>
> gcc/
>         * genmatch.c (write_predicate): Add ATTRIBUTE_UNUSED.
>         * fold-const.c (fold_binary_loc): Remove 2 transformations
>         superseded by match.pd.
>         * match.pd (x+x -> x*2): Generalize to integers.
>
> gcc/testsuite/
>         * gcc.dg/fold-plusmult.c: Adjust.
>         * gcc.dg/no-strict-overflow-6.c: Adjust.
>         * gcc.dg/gomp/loop-1.c: Xfail some tests.
>
> --
> Marc Glisse
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    (revision 235411)
> +++ gcc/fold-const.c    (working copy)
> @@ -9949,39 +9949,20 @@ fold_binary_loc (location_t loc,
>           /* Transform x * -C into -x * C if x is easily negatable.  */
>           if (TREE_CODE (op1) == INTEGER_CST
>               && tree_int_cst_sgn (op1) == -1
>               && negate_expr_p (op0)
>               && (tem = negate_expr (op1)) != op1
>               && ! TREE_OVERFLOW (tem))
>             return fold_build2_loc (loc, MULT_EXPR, type,
>                                     fold_convert_loc (loc, type,
>                                                       negate_expr (op0)),
> tem);
>
> -         /* (A + A) * C -> A * 2 * C  */
> -         if (TREE_CODE (arg0) == PLUS_EXPR
> -             && TREE_CODE (arg1) == INTEGER_CST
> -             && operand_equal_p (TREE_OPERAND (arg0, 0),
> -                                 TREE_OPERAND (arg0, 1), 0))
> -           return fold_build2_loc (loc, MULT_EXPR, type,
> -                               omit_one_operand_loc (loc, type,
> -                                                 TREE_OPERAND (arg0, 0),
> -                                                 TREE_OPERAND (arg0, 1)),
> -                               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,
>                                              &strict_overflow_p)))
>             {
>               if (strict_overflow_p)
>                 fold_overflow_warning (("assuming signed overflow does not "
>                                         "occur when simplifying "
>                                         "multiplication"),
>                                        WARN_STRICT_OVERFLOW_MISC);
> Index: gcc/genmatch.c
> ===================================================================
> --- gcc/genmatch.c      (revision 235411)
> +++ gcc/genmatch.c      (working copy)
> @@ -3549,21 +3549,21 @@ decision_tree::gen (FILE *f, bool gimple
>
>  /* Output code to implement the predicate P from the decision tree DT.  */
>
>  void
>  write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
>  {
>    fprintf (f, "\nbool\n"
>            "%s%s (tree t%s%s)\n"
>            "{\n", gimple ? "gimple_" : "tree_", p->id,
>            p->nargs > 0 ? ", tree *res_ops" : "",
> -          gimple ? ", tree (*valueize)(tree)" : "");
> +          gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : "");
>    /* Conveniently make 'type' available.  */
>    fprintf_indent (f, 2, "tree type = TREE_TYPE (t);\n");
>
>    if (!gimple)
>      fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
>    dt.root->gen_kids (f, 2, gimple);
>
>    fprintf_indent (f, 2, "return false;\n"
>            "}\n");
>  }
> Index: gcc/match.pd
> ===================================================================
> --- gcc/match.pd        (revision 235411)
> +++ gcc/match.pd        (working copy)
> @@ -1621,25 +1621,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  /* Canonicalization of binary operations.  */
>
>  /* Convert X + -C into X - C.  */
>  (simplify
>   (plus @0 REAL_CST@1)
>   (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
>    (with { tree tem = const_unop (NEGATE_EXPR, type, @1); }
>     (if (!TREE_OVERFLOW (tem) || !flag_trapping_math)
>      (minus @0 { tem; })))))
>
> -/* Convert x+x into x*2.0.  */
> +/* Convert x+x into x*2.  */
>  (simplify
>   (plus @0 @0)
>   (if (SCALAR_FLOAT_TYPE_P (type))
> -  (mult @0 { build_real (type, dconst2); })))
> +  (mult @0 { build_real (type, dconst2); })
> +  (if (INTEGRAL_TYPE_P (type))
> +   (mult @0 { build_int_cst (type, 2); }))))
>
>  (simplify
>   (minus integer_zerop @1)
>   (negate @1))
>
>  /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0).  So check whether
>     ARG0 is zero and X + ARG0 reduces to X, since that would mean
>     (-ARG1 + ARG0) reduces to -ARG1.  */
>  (simplify
>   (minus real_zerop@0 @1)
> Index: gcc/testsuite/gcc.dg/fold-plusmult.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/fold-plusmult.c        (revision 235411)
> +++ gcc/testsuite/gcc.dg/fold-plusmult.c        (working copy)
> @@ -4,11 +4,11 @@
>  int test1 (int a)
>  {
>    return 2*a + 2*a;
>  }
>
>  int test2 (int a)
>  {
>    return (a + a)*2;
>  }
>
> -/* { dg-final { scan-tree-dump-times "<a> \\\* 4" 2 "original" } } */
> +/* { dg-final { scan-tree-dump-times "a \\\* 4" 2 "original" } } */
> Index: gcc/testsuite/gcc.dg/gomp/loop-1.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/gomp/loop-1.c  (revision 235411)
> +++ gcc/testsuite/gcc.dg/gomp/loop-1.c  (working copy)
> @@ -37,28 +37,28 @@ f1 (int x)
>      ;
>    #pragma omp for
>    for (i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers
> to iteration variable" } */
>      ;
>    #pragma omp for
>    for (i = 5; i <= baz (&i); i++) /* { dg-error "condition expression
> refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (i = 5; i <= i; i++) /* { dg-error "invalid controlling
> predicate|condition expression refers to iteration variable" } */
>      ;
> -  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" } */
> -  for (i = 5; i < 16; i += i)
> +  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" "" { xfail *-*-* } } */
> +  for (i = 5; i < 16; i += i) /* { dg-bogus "invalid increment expression"
> "" { xfail *-*-* } } */
>      ;
>    #pragma omp for
>    for (i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment
> expression|increment expression refers to iteration variable" } */
>      ;
> -  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" } */
> -  for (i = 5; i < 16; i = i + i)
> +  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" "" { xfail *-*-* } } */
> +  for (i = 5; i < 16; i = i + i) /* { dg-bogus "invalid increment
> expression" "" { xfail *-*-* } } */
>      ;
>    #pragma omp for
>    for (i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression
> refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression
> refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression
> refers to iteration variable" } */
>      ;
> @@ -174,28 +174,28 @@ f2 (int x)
>      ;
>    #pragma omp for
>    for (int i = 5; bar (i) > i; i++) /* { dg-error "condition expression
> refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (int i = 5; i <= baz (&i); i++) /* { dg-error "condition expression
> refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (int i = 5; i <= i; i++) /* { dg-error "invalid controlling
> predicate|condition expression refers to iteration variable" } */
>      ;
> -  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" } */
> -  for (int i = 5; i < 16; i += i)
> +  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" "" { xfail *-*-* } } */
> +  for (int i = 5; i < 16; i += i) /* { dg-bogus "invalid increment
> expression" "" { xfail *-*-* } } */
>      ;
>    #pragma omp for
>    for (int i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment
> expression|increment expression refers to iteration variable" } */
>      ;
> -  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" } */
> -  for (int i = 5; i < 16; i = i + i)
> +  #pragma omp for /* { dg-error "increment expression refers to iteration
> variable" "" { xfail *-*-* } } */
> +  for (int i = 5; i < 16; i = i + i) /* { dg-bogus "invalid increment
> expression" "" { xfail *-*-* } } */
>      ;
>    #pragma omp for
>    for (int i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment
> expression refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (int i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment
> expression refers to iteration variable" } */
>      ;
>    #pragma omp for
>    for (int i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression
> refers to iteration variable" } */
>      ;
> Index: gcc/testsuite/gcc.dg/no-strict-overflow-6.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/no-strict-overflow-6.c (revision 235411)
> +++ gcc/testsuite/gcc.dg/no-strict-overflow-6.c (working copy)
> @@ -7,14 +7,14 @@
>     strict overflow semantics.  We don't test this with
>     -fstrict-overflow because it turns into an infinite loop.  That is
>     OK but it would also be OK to not do that.  */
>
>  int
>  foo ()
>  {
>    int i, bits;
>    for (i = 1, bits = 1; i > 0; i += i)
>      ++bits;
> -  return bits;
> +  return bits - sizeof(int) * __CHAR_BIT__;
>  }
>
> -/* { dg-final { scan-tree-dump "return bits" "optimized" } } */
> +/* { dg-final { scan-tree-dump "return 0" "optimized" } } */
>

Reply via email to