diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b97fb081f5cfdba485672a3012efc22163fbc3f4..026dade34713197cb962cce8e34a617ffefd2be8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2006-01-05  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/22555
+	* tree-ssa-alias.c (create_overlap_variables_for): Do not give up,
+	if one structure field is an array.
+	* tree-ssa-operands.c (get_expr_operands): Continue scanning
+	operands even if we found a subvar, but ignore VOPs in this
+	case.
+	* tree-ssa-loop-ivopts.c (rewrite_use): Mark new vars in stmt
+	for renaming.
+	* tree-ssa-loop.c (pass_iv_optimize): Schedule TODO_update_ssa.
+
 2006-01-05  Richard Earnshaw  <rearnsha@arm.com>
 
 	PR middle-end/24998
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c3c35f14458273579ded94385ed851e2fa2e8059..640c92605e008c29ec2ba078158df7cb008607e2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-01-05  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/22555
+	* gcc.dg/tree-ssa/alias-3.c: New testcase.
+
 2006-01-05  Richard Guenther  <rguenther@suse.de>
 	    Diego Novillo  <dnovillo@redhat.com>
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-3.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d8587da89bd161e832e759d5ae85aac248ba91b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct {
+	int i;
+	int j;
+	int x[2];
+} a;
+
+int foo(void)
+{
+	a.i = 1;
+	a.j = 0;
+	a.x[0] = 0;
+	return a.i + a.j;
+}
+
+/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 5813a653b15870f0859d0eb5da4d2dc028aba0f9..ee6a6e6a49ec34159b6c7493d1d0d93aa8343b9d 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2580,7 +2580,6 @@ create_overlap_variables_for (tree var)
 	{
 	  if (!fo->size
 	      || TREE_CODE (fo->size) != INTEGER_CST
-	      || TREE_CODE (fo->type) == ARRAY_TYPE
 	      || fo->offset < 0)
 	    {
 	      notokay = true;
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 6e7dd61673eeecdb80e2a0a76181228bbcdaa591..4c7d64560c9e0c90e4892de9f806c4f18401d68b 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5825,7 +5825,7 @@ rewrite_use (struct ivopts_data *data,
       default:
 	gcc_unreachable ();
     }
-  update_stmt (use->stmt);
+  mark_new_vars_to_rename (use->stmt);
 }
 
 /* Rewrite the uses using the selected induction variables.  */
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 34126b16fa0401ef6b560f7921b64a6b9ff1d6ed..8565f255223addb667aca9f135394952e54f4144 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -432,7 +432,9 @@ struct tree_opt_pass pass_iv_optimize =
   0,					/* properties_provided */
   0,					/* properties_destroyed */
   0,					/* todo_flags_start */
-  TODO_dump_func | TODO_verify_loops,	/* todo_flags_finish */
+  TODO_dump_func
+  | TODO_verify_loops
+  | TODO_update_ssa,			/* todo_flags_finish */
   0					/* letter */
 };
 
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 01bf7f21ae0122525350269faeb49c074056e54a..b7319deffb2d20b88ed5c41a78e5de7bc0f98172 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1126,6 +1126,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       {
 	tree ref;
 	HOST_WIDE_INT offset, size, maxsize;
+	bool none = true;
  	/* This component ref becomes an access to all of the subvariables
 	   it can touch,  if we can determine that, but *NOT* the real one.
 	   If we can't determine which fields we could touch, the recursion
@@ -1143,16 +1144,22 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
 		if (overlap_subvar (offset, maxsize, sv, &exact))
 		  {
 	            int subvar_flags = flags;
+		    none = false;
 		    if (!exact
 			|| size != maxsize)
 		      subvar_flags &= ~opf_kill_def;
 		    add_stmt_operand (&sv->var, s_ann, subvar_flags);
 		  }
 	      }
+	    if (!none)
+	      flags |= opf_no_vops;
 	  }
-	else
-	  get_expr_operands (stmt, &TREE_OPERAND (expr, 0), 
-			     flags & ~opf_kill_def);
+
+	/* Even if we found subvars above we need to ensure to see
+	   immediate uses for d in s.a[d].  In case of s.a having
+	   a subvar we'd miss it otherwise.  */
+	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), 
+			   flags & ~opf_kill_def);
 	
 	if (code == COMPONENT_REF)
 	  {