This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

match.pd: x+x -> 2*x


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.

2016-04-26  Marc Glisse  <marc.glisse@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" } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]