diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 61c529102a98eb4b417cd3a1d1a0bd11609c39f5..1d8f4a9650070ed1f740eab41c93cf0f9739b5a0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2009-11-20 Olga Golovanevsky <olga@il.ibm.com>
+
+	PR middle-end/39960
+	* ipa-struct-reorg.c (find_pos_in_stmt): New parameter.
+	(ref_pos): New field in structure.
+	(insert_new_var_in_stmt): New function.
+
+
 2009-11-20  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
 	* config.gcc (alpha*-dec-osf[45]*): Set use_gcc_stdint.
diff --git a/gcc/ipa-struct-reorg.c b/gcc/ipa-struct-reorg.c
index 65777f59394ed2a3d40c46e24bc063d162238b54..d2187b82b99db20cccd7552e2aa7e963582c3d03 100644
--- a/gcc/ipa-struct-reorg.c
+++ b/gcc/ipa-struct-reorg.c
@@ -868,6 +868,7 @@ struct ref_pos
 {
   tree *pos;
   tree ref;
+  tree container;
 };
 
 
@@ -890,6 +891,7 @@ find_pos_in_stmt_1 (tree *tp, int *walk_subtrees, void * data)
       return t;
     }
 
+  r_pos->container = t;
   *walk_subtrees = 1;      
   return NULL_TREE;
 }
@@ -899,18 +901,18 @@ find_pos_in_stmt_1 (tree *tp, int *walk_subtrees, void * data)
    It returns it, if found, and NULL otherwise.  */
 
 static tree *
-find_pos_in_stmt (gimple stmt, tree ref)
+find_pos_in_stmt (gimple stmt, tree ref, struct ref_pos * r_pos)
 {
-  struct ref_pos r_pos;
   struct walk_stmt_info wi;
 
-  r_pos.ref = ref;
-  r_pos.pos = NULL;
+  r_pos->ref = ref;
+  r_pos->pos = NULL;
+  r_pos->container = NULL_TREE;
   memset (&wi, 0, sizeof (wi));
-  wi.info = &r_pos;
+  wi.info = r_pos;
   walk_gimple_op (stmt, find_pos_in_stmt_1, &wi);
 
-  return r_pos.pos;
+  return r_pos->pos;
 }
 
 /* This structure is used to represent array 
@@ -948,6 +950,7 @@ replace_field_acc (struct field_access_site *acc, tree new_type)
   tree field_id = DECL_NAME (acc->field_decl);
   VEC (type_wrapper_t, heap) *wrapper = VEC_alloc (type_wrapper_t, heap, 10);
   type_wrapper_t *wr_p = NULL;
+  struct ref_pos r_pos;
   
   while (TREE_CODE (ref_var) == INDIRECT_REF
 	 || TREE_CODE (ref_var) == ARRAY_REF)
@@ -999,14 +1002,14 @@ replace_field_acc (struct field_access_site *acc, tree new_type)
 	gimple_assign_set_rhs1 (acc->stmt, new_acc);
       else
 	{
-	  pos = find_pos_in_stmt (acc->stmt, acc->comp_ref);
+	  pos = find_pos_in_stmt (acc->stmt, acc->comp_ref, &r_pos);
 	  gcc_assert (pos);
 	  *pos = new_acc;
 	}
     }
   else
     {
-      pos = find_pos_in_stmt (acc->stmt, acc->comp_ref);
+      pos = find_pos_in_stmt (acc->stmt, acc->comp_ref, &r_pos);
       gcc_assert (pos);
       *pos = new_acc;
     }
@@ -1244,6 +1247,35 @@ create_new_stmts_for_cond_expr (gimple stmt)
     }
 }
 
+/* This function looks for VAR in STMT, and replace it with NEW_VAR.
+   If needed, it wraps NEW_VAR in pointers and indirect references 
+   before insertion.  */
+
+static void
+insert_new_var_in_stmt (gimple stmt, tree var, tree new_var)
+{
+  struct ref_pos r_pos;
+  tree *pos;
+
+  pos = find_pos_in_stmt (stmt, var, &r_pos);
+  gcc_assert (pos);
+
+  while (r_pos.container && (TREE_CODE(r_pos.container) == INDIRECT_REF
+			     || TREE_CODE(r_pos.container) == ADDR_EXPR))
+    {
+      tree type = TREE_TYPE (TREE_TYPE (new_var));
+
+      if (TREE_CODE(r_pos.container) == INDIRECT_REF)		    
+	new_var = build1 (INDIRECT_REF, type, new_var);
+      else
+	new_var = build_fold_addr_expr (new_var);
+      pos = find_pos_in_stmt (stmt, r_pos.container, &r_pos);
+    }
+	      
+  *pos = new_var;
+}
+
+
 /* Create a new general access to replace original access ACC
    for structure type NEW_TYPE.  */
 
@@ -1264,7 +1296,6 @@ create_general_new_stmt (struct access_site *acc, tree new_type)
 
   for (i = 0; VEC_iterate (tree, acc->vars, i, var); i++)
     {
-      tree *pos;
       tree new_var = find_new_var_of_type (var, new_type);
       tree lhs, rhs = NULL_TREE;
 
@@ -1296,20 +1327,10 @@ create_general_new_stmt (struct access_site *acc, tree new_type)
 	  else if (rhs == var)
 	    gimple_assign_set_rhs1 (new_stmt, new_var);
 	  else
-	    {
-	      pos = find_pos_in_stmt (new_stmt, var);
-	      gcc_assert (pos);
-	      /* ???  This misses adjustments to the type of the
-	         INDIRECT_REF we possibly replace the operand of.  */
-	      *pos = new_var;
-	    }      
+	    insert_new_var_in_stmt (new_stmt, var, new_var);
 	}
       else
-	{
-	  pos = find_pos_in_stmt (new_stmt, var);
-	  gcc_assert (pos);
-	  *pos = new_var;
-	}
+	insert_new_var_in_stmt (new_stmt, var, new_var);
     }
 
   finalize_stmt (new_stmt);