diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 16e7d234a0d7e5922e9089084f4e78aab8682d3b..42d8bf4fe50c419613aeea2ba1a95567dc6aa402 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2009-08-13  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/41047
+	* tree-ssa-ccp.c (ccp_fold): When folding pointer additions
+	use the constant pointer type.
+	* gimplify.c (canonicalize_addr_expr): Canonicalize independent
+	of CV qualifiers on the target pointer type.
+	* tree-ssa.c (useless_type_conversion_p): Move incomplete pointer
+	conversion check before restrict check.
+
 2009-08-12  Kaz Kojima  <kkojima@gcc.gnu.org>
 
 	PR target/41029
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index eaea16df19ca281d5628ef77e95aa3eb313630be..7de2a7e183f2a9f0f3a5b8fe64a4cc1ae81ed2c5 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1763,7 +1763,8 @@ canonicalize_addr_expr (tree *expr_p)
      the expression pointer type.  */
   ddatype = TREE_TYPE (datype);
   pddatype = build_pointer_type (ddatype);
-  if (!useless_type_conversion_p (pddatype, ddatype))
+  if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
+				  pddatype))
     return;
 
   /* The lower bound and element sizes must be constant.  */
@@ -1778,6 +1779,10 @@ canonicalize_addr_expr (tree *expr_p)
 		    TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
 		    NULL_TREE, NULL_TREE);
   *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
+
+  /* We can have stripped a required restrict qualifier above.  */
+  if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
+    *expr_p = fold_convert (TREE_TYPE (expr), *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 fd1aa264cea479b81ab34817e336fe39104b6ce2..92575a3e06ae261d5f013b09c6403a1b8fa115d8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-08-13  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/41047
+	* gcc.dg/tree-ssa/ssa-ccp-27.c: New testcase.
+
 2009-08-12  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/41011
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-27.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-27.c
new file mode 100644
index 0000000000000000000000000000000000000000..c27963454713d4f52fbe88fe78aa69331ede6dea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-27.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ccp1" } */
+
+#include <string.h>
+
+char c[10];
+
+void
+f1 ()
+{
+  const char *p = "123456";
+  memcpy (c, p, 6);
+}
+
+void
+f2 ()
+{
+  const char *p = "12345678";
+  p += 2;
+  memcpy (c, p, 6);
+}
+
+/* { dg-final { scan-tree-dump-times "memcpy\[^\n\]*123456" 2 "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index f39d272964bbc96f3f970c4e8528e4b0307d7f28..b359d4c8d767fb0bdc2c17f75a0b4259cd4e36de 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1093,9 +1093,8 @@ ccp_fold (gimple stmt)
 		  && TREE_CODE (op0) == ADDR_EXPR
 		  && TREE_CODE (op1) == INTEGER_CST)
 		{
-		  tree lhs = gimple_assign_lhs (stmt);
 		  tree tem = maybe_fold_offset_to_address
-		    (loc, op0, op1, TREE_TYPE (lhs));
+		    (loc, op0, op1, TREE_TYPE (op0));
 		  if (tem != NULL_TREE)
 		    return tem;
 		}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index a40270335df7c7c8e3062f07a46b9a4cde3711a6..76e4e8b7f1b3c0ae0e18eae355cb424ac4b92828 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -874,6 +874,16 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
   if (POINTER_TYPE_P (inner_type)
       && POINTER_TYPE_P (outer_type))
     {
+      /* If the outer type is (void *) or a pointer to an incomplete
+	 record type, then the conversion is not necessary.  */
+      if (VOID_TYPE_P (TREE_TYPE (outer_type))
+	  || (AGGREGATE_TYPE_P (TREE_TYPE (outer_type))
+	      && TREE_CODE (TREE_TYPE (outer_type)) != ARRAY_TYPE
+	      && (TREE_CODE (TREE_TYPE (outer_type))
+		  == TREE_CODE (TREE_TYPE (inner_type)))
+	      && !COMPLETE_TYPE_P (TREE_TYPE (outer_type))))
+	return true;
+
       /* Do not lose casts to restrict qualified pointers.  */
       if ((TYPE_RESTRICT (outer_type)
 	   != TYPE_RESTRICT (inner_type))
@@ -930,16 +940,6 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
   else if (POINTER_TYPE_P (inner_type)
 	   && POINTER_TYPE_P (outer_type))
     {
-      /* If the outer type is (void *) or a pointer to an incomplete
-	 record type, then the conversion is not necessary.  */
-      if (VOID_TYPE_P (TREE_TYPE (outer_type))
-	  || (AGGREGATE_TYPE_P (TREE_TYPE (outer_type))
-	      && TREE_CODE (TREE_TYPE (outer_type)) != ARRAY_TYPE
-	      && (TREE_CODE (TREE_TYPE (outer_type))
-		  == TREE_CODE (TREE_TYPE (inner_type)))
-	      && !COMPLETE_TYPE_P (TREE_TYPE (outer_type))))
-	return true;
-
       /* Don't lose casts between pointers to volatile and non-volatile
 	 qualified types.  Doing so would result in changing the semantics
 	 of later accesses.  For function types the volatile qualifier