diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 798ea8244030ec75eb191d3be56861960d5d24de..1b3b0fc213ca97b6a245a06f4668ae4002c6913f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-19  Richard Guenther  <rguenther@suse.de>
+
+	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Do
+	not falsely claim to have propagated into all uses.
+
 2009-05-19  Ben Elliston  <bje@au.ibm.com>
 
 	* doc/invoke.texi (C Dialect Options): Update OpenMP specification
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 34a7a2d0a4a19525fa0e43a0df6e64264e84a8f7..44019be7e3fb1e6c3de47572fab0166167e4a10a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2009-05-19  Richard Guenther  <rguenther@suse.de>
+
+	* gcc.c-torture/compile/20090519-1.c: New testcase.
+
 2009-05-18  Jason Merrill  <jason@redhat.com>
 
 	* g++.dg/cpp0x/explicit1.C: New.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20090519-1.c b/gcc/testsuite/gcc.c-torture/compile/20090519-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..54add6b2e1a0f1b3a882312f6e8537fc8a4f4131
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20090519-1.c
@@ -0,0 +1,11 @@
+typedef struct { int licensed;  } __pmPDUInfo;
+void __pmDecodeXtendError (int *);
+void do_handshake(void)
+{
+  __pmPDUInfo *pduinfo;
+  int challenge;
+  __pmDecodeXtendError(&challenge);
+  pduinfo = (__pmPDUInfo *)&challenge;
+  *pduinfo = *pduinfo;
+}
+
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 31f2ad71640b74f578bf997148f78c7d0b28cf80..4549ae49ffd3897df49162a6f19c9434865b9bec 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -717,6 +717,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
   tree *rhsp, *lhsp;
   gimple use_stmt = gsi_stmt (*use_stmt_gsi);
   enum tree_code rhs_code;
+  bool res = true;
 
   gcc_assert (TREE_CODE (def_rhs) == ADDR_EXPR);
 
@@ -764,19 +765,26 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
   /* Now see if the LHS node is an INDIRECT_REF using NAME.  If so, 
      propagate the ADDR_EXPR into the use of NAME and fold the result.  */
   if (TREE_CODE (lhs) == INDIRECT_REF
-      && TREE_OPERAND (lhs, 0) == name
-      && may_propagate_address_into_dereference (def_rhs, lhs)
-      && (lhsp != gimple_assign_lhs_ptr (use_stmt)
-	  || useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
-					TREE_TYPE (rhs))))
+      && TREE_OPERAND (lhs, 0) == name)
     {
-      *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
-      fold_stmt_inplace (use_stmt);
-      tidy_after_forward_propagate_addr (use_stmt);
+      if (may_propagate_address_into_dereference (def_rhs, lhs)
+	  && (lhsp != gimple_assign_lhs_ptr (use_stmt)
+	      || useless_type_conversion_p
+	           (TREE_TYPE (TREE_OPERAND (def_rhs, 0)), TREE_TYPE (rhs))))
+	{
+	  *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
+	  fold_stmt_inplace (use_stmt);
+	  tidy_after_forward_propagate_addr (use_stmt);
 
-      /* Continue propagating into the RHS if this was not the only use.  */
-      if (single_use_p)
-	return true;
+	  /* Continue propagating into the RHS if this was not the only use.  */
+	  if (single_use_p)
+	    return true;
+	}
+      else
+	/* We can have a struct assignment dereferencing our name twice.
+	   Note that we didn't propagate into the lhs to not falsely
+	   claim we did when propagating into the rhs.  */
+	res = false;
     }
 
   /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
@@ -796,7 +804,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
       *rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
       fold_stmt_inplace (use_stmt);
       tidy_after_forward_propagate_addr (use_stmt);
-      return true;
+      return res;
     }
 
   /* Now see if the RHS node is an INDIRECT_REF using NAME.  If so, 
@@ -827,7 +835,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
 					     true, GSI_NEW_STMT);
 	 gimple_assign_set_rhs1 (use_stmt, new_rhs);
 	 tidy_after_forward_propagate_addr (use_stmt);
-	 return true;
+	 return res;
        }
      /* If the defining rhs comes from an indirect reference, then do not
         convert into a VIEW_CONVERT_EXPR.  */
@@ -841,7 +849,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
 	 *rhsp = new_rhs;
 	 fold_stmt_inplace (use_stmt);
 	 tidy_after_forward_propagate_addr (use_stmt);
-	 return true;
+	 return res;
        }
    }