From 04d86531d7cf2080903ea85d27d79daa944828fb Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Tue, 4 Sep 2007 08:38:56 +0000
Subject: [PATCH] re PR tree-optimization/33291 (a+=2; a+=2  not simplified to 
 a+=4;  with -O3   (ok with gcc-4.2.1))

2007-09-04  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33291
	* tree-pretty-print.c (dump_generic_node): Dump all
	qualifiers for pointer types, not only first.  Dump
	qualifiers for aggregate types as well.
	* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Always
	use the canonical type for building ARRAY_REFs.
	* gimplify.c (canonicalize_addr_expr): Clean up.  The
	correct validness check is compatibility of the pointer
	types.  Always use the canonical type for building
	ARRAY_REFs and ADDR_EXPRs.
	* tree-ssa-forwprop.c (forward_propagate_addr_expr): Revert
	change that disabled propagation of ADDR_EXPRs into statements
	with volatile ops.

	* gcc.dg/volatile2.c: New testcase.
	* gcc.dg/pr32721.c: Adjust volatile reference pattern.
	* gcc.dg/tree-ssa/forwprop-1.c: Remove xfail.
	* gcc.dg/tree-ssa/forwprop-2.c: Likewise.
	* gcc.dg/tree-ssa/pr17141-1.c: Likewise.

From-SVN: r128068
---
 gcc/ChangeLog                              | 16 ++++++++++
 gcc/gimplify.c                             | 36 ++++++++++------------
 gcc/testsuite/ChangeLog                    |  9 ++++++
 gcc/testsuite/gcc.dg/pr32721.c             |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c |  9 ++----
 gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c |  5 ++-
 gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c  |  7 ++---
 gcc/testsuite/gcc.dg/volatile2.c           | 25 +++++++++++++++
 gcc/tree-pretty-print.c                    | 35 +++++++++++++--------
 gcc/tree-ssa-ccp.c                         |  2 +-
 gcc/tree-ssa-forwprop.c                    |  7 -----
 11 files changed, 98 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/volatile2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c469388519b8..75bea70a5d04 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2007-09-04  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/33291
+	* tree-pretty-print.c (dump_generic_node): Dump all
+	qualifiers for pointer types, not only first.  Dump
+	qualifiers for aggregate types as well.
+	* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Always
+	use the canonical type for building ARRAY_REFs.
+	* gimplify.c (canonicalize_addr_expr): Clean up.  The
+	correct validness check is compatibility of the pointer
+	types.  Always use the canonical type for building
+	ARRAY_REFs and ADDR_EXPRs.
+	* tree-ssa-forwprop.c (forward_propagate_addr_expr): Revert
+	change that disabled propagation of ADDR_EXPRs into statements
+	with volatile ops.
+
 2007-09-03  Zack Weinberg  <zack@codesourcery.com>
 
 	* config/arm/arm.md (mulsidi3, umulsidi3, mulsi3_highpart)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index aed8ab769496..572a34fa6b3f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1572,50 +1572,46 @@ canonicalize_component_ref (tree *expr_p)
    ==>
       &array[L]
    where L is the lower bound.  For simplicity, only do this for constant
-   lower bound.  */
+   lower bound.
+   The constraint is that the type of &array[L] is trivially convertible
+   to T *.  */
 
 static void
 canonicalize_addr_expr (tree *expr_p)
 {
   tree expr = *expr_p;
-  tree ctype = TREE_TYPE (expr);
   tree addr_expr = TREE_OPERAND (expr, 0);
-  tree atype = TREE_TYPE (addr_expr);
-  tree dctype, datype, ddatype, otype, obj_expr;
+  tree datype, ddatype, pddatype;
 
-  /* Both cast and addr_expr types should be pointers.  */
-  if (!POINTER_TYPE_P (ctype) || !POINTER_TYPE_P (atype))
+  /* We simplify only conversions from an ADDR_EXPR to a pointer type.  */
+  if (!POINTER_TYPE_P (TREE_TYPE (expr))
+      || TREE_CODE (addr_expr) != ADDR_EXPR)
     return;
 
   /* The addr_expr type should be a pointer to an array.  */
-  datype = TREE_TYPE (atype);
+  datype = TREE_TYPE (TREE_TYPE (addr_expr));
   if (TREE_CODE (datype) != ARRAY_TYPE)
     return;
 
-  /* Both cast and addr_expr types should address the same object type.  */
-  dctype = TREE_TYPE (ctype);
+  /* The pointer to element type shall be trivially convertible to
+     the expression pointer type.  */
   ddatype = TREE_TYPE (datype);
-  if (!useless_type_conversion_p (dctype, ddatype))
-    return;
-
-  /* The addr_expr and the object type should match.  */
-  obj_expr = TREE_OPERAND (addr_expr, 0);
-  otype = TREE_TYPE (obj_expr);
-  if (!useless_type_conversion_p (datype, otype))
+  pddatype = build_pointer_type (ddatype);
+  if (!useless_type_conversion_p (pddatype, ddatype))
     return;
 
   /* The lower bound and element sizes must be constant.  */
-  if (!TYPE_SIZE_UNIT (dctype)
-      || TREE_CODE (TYPE_SIZE_UNIT (dctype)) != INTEGER_CST
+  if (!TYPE_SIZE_UNIT (ddatype)
+      || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
       || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
       || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
     return;
 
   /* All checks succeeded.  Build a new node to merge the cast.  */
-  *expr_p = build4 (ARRAY_REF, dctype, obj_expr,
+  *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
 		    TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
 		    NULL_TREE, NULL_TREE);
-  *expr_p = build1 (ADDR_EXPR, ctype, *expr_p);
+  *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
 }
 
 /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR.  Remove it and/or other conversions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e98ef3425445..1fcf11e92efd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2007-09-04  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/33291
+	* gcc.dg/volatile2.c: New testcase.
+	* gcc.dg/pr32721.c: Adjust volatile reference pattern.
+	* gcc.dg/tree-ssa/forwprop-1.c: Remove xfail.
+	* gcc.dg/tree-ssa/forwprop-2.c: Likewise.
+	* gcc.dg/tree-ssa/pr17141-1.c: Likewise.
+
 2007-09-03  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR fortran/33253
diff --git a/gcc/testsuite/gcc.dg/pr32721.c b/gcc/testsuite/gcc.dg/pr32721.c
index bd67c79521ec..2f3a18a8815b 100644
--- a/gcc/testsuite/gcc.dg/pr32721.c
+++ b/gcc/testsuite/gcc.dg/pr32721.c
@@ -14,5 +14,5 @@ spinlock1 = &spinlock[1];
  while (*spinlock0);
 }
 
-/* { dg-final { scan-tree-dump "={v} spinlock.0." "optimized" } } */
+/* { dg-final { scan-tree-dump "={v} \\*spinlock0" "optimized" } } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c
index ee7f049c6643..c1fa43543c14 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-forwprop" }  */
+/* { dg-options "-O2 -fdump-tree-forwprop1" }  */
 
 /* We should be able to optimize this to b->t[i] = 1 during
    early optimizations.  */
@@ -15,8 +15,5 @@ void f(struct a * b, __SIZE_TYPE__ i)
   c[i] = 1;
 }
 
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop2" } } */
-/* { dg-final { cleanup-tree-dump "forwprop?" } } */
-
-
+/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c
index 95aa77eb3f7a..434d86c65d5b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-forwprop" }  */
+/* { dg-options "-O2 -fdump-tree-forwprop1" }  */
 
 /* We should be able to optimize this to b->t[i] = 1 during
    early optimizations.  */
@@ -17,6 +17,5 @@ void f(__SIZE_TYPE__ i)
   c[i] = 1;
 }
 
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop2" } } */
+/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" } } */
 /* { dg-final { cleanup-tree-dump "forwprop?" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c
index f517c89b1856..af8675150025 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-forwprop" } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" } */
 
 struct A { int i; };
 int
@@ -11,6 +11,5 @@ foo(struct A *locp, int str)
   return locp->i;
 }
 
-/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop2" } } */
-/* { dg-final { cleanup-tree-dump "forwprop?" } } */
+/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/volatile2.c b/gcc/testsuite/gcc.dg/volatile2.c
new file mode 100644
index 000000000000..4bfc441c862f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/volatile2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-gimple -fdump-tree-optimized" } */
+
+struct GTeth_desc
+{
+  unsigned ed_cmdsts;
+};
+struct GTeth_softc
+{
+  struct GTeth_desc txq_desc[32];
+};
+
+void foo(struct GTeth_softc *sc)
+{
+  /* Verify that we retain the cast to (volatile struct GTeth_desc *)
+     after gimplification and that we keep the volatileness on the
+     store until after optimization.  */
+  volatile struct GTeth_desc *p = &sc->txq_desc[0];
+  p->ed_cmdsts = 0;
+}
+
+/* { dg-final { scan-tree-dump "\\(volatile struct GTeth_desc \\*\\) D" "gimple" } } */
+/* { dg-final { scan-tree-dump "{v}" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index acc16d54da80..c1fd68be430c 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -622,9 +622,9 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
 
 	  if (quals & TYPE_QUAL_CONST)
 	    pp_string (buffer, " const");
-	  else if (quals & TYPE_QUAL_VOLATILE)
-	    pp_string (buffer,  "volatile");
-	  else if (quals & TYPE_QUAL_RESTRICT)
+	  if (quals & TYPE_QUAL_VOLATILE)
+	    pp_string (buffer, " volatile");
+	  if (quals & TYPE_QUAL_RESTRICT)
 	    pp_string (buffer, " restrict");
 
 	  if (TYPE_REF_CAN_ALIAS_ALL (node))
@@ -718,17 +718,26 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      /* Print the name of the structure.  */
-      if (TREE_CODE (node) == RECORD_TYPE)
-	pp_string (buffer, "struct ");
-      else if (TREE_CODE (node) == UNION_TYPE)
-	pp_string (buffer, "union ");
+      {
+	unsigned int quals = TYPE_QUALS (node);
 
-      if (TYPE_NAME (node))
-	dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false);
-      else
-	print_struct_decl (buffer, node, spc, flags);
-      break;
+	if (quals & TYPE_QUAL_CONST)
+	  pp_string (buffer, "const ");
+	if (quals & TYPE_QUAL_VOLATILE)
+	  pp_string (buffer, "volatile ");
+
+        /* Print the name of the structure.  */
+        if (TREE_CODE (node) == RECORD_TYPE)
+	  pp_string (buffer, "struct ");
+        else if (TREE_CODE (node) == UNION_TYPE)
+	  pp_string (buffer, "union ");
+
+        if (TYPE_NAME (node))
+	  dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false);
+        else
+	  print_struct_decl (buffer, node, spc, flags);
+        break;
+      }
 
     case LANG_TYPE:
       NIY;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index e0829f599170..05a65f6e093f 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1644,7 +1644,7 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
   /* Make sure to possibly truncate late after offsetting.  */
   idx = fold_convert (idx_type, idx);
 
-  return build4 (ARRAY_REF, orig_type, base, idx, NULL_TREE, NULL_TREE);
+  return build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
 }
 
 
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index cac5d0ae3691..e026b804d40d 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -717,13 +717,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
 	  continue;
 	}
 
-      /* If the use_stmt has side-effects, don't propagate into it.  */
-      if (stmt_ann (use_stmt)->has_volatile_ops)
-	{
-	  all = false;
-	  continue;
-	}
-
       push_stmt_changes (&use_stmt);
 
       result = forward_propagate_addr_expr_1 (name, rhs, use_stmt,
-- 
GitLab