diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 23ccab683a2d4f27af893785b56c980fcdd43f8d..9384f1705a90c28afe6a48dddece0d1e5ca0a29b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-10-15  Richard Henderson  <rth@redhat.com>
+
+	* gimplify.c (gimplify_var_or_parm_decl): Split out from ...
+	(gimplify_expr): ... here.
+	(gimplify_compound_lval): Use it in initial scan loop.  Allow
+	fb_lvalue in base expression.
+
 2005-10-15  Richard Henderson  <rth@redhat.com>
 
 	PR 23714
@@ -418,7 +425,7 @@
 2005-10-06  Daniel Berlin  <dberlin@dberlin.org>
 	
 	* tree-ssa-structalias.c (check_for_overlaps): Fix bug in last
-        change.
+	change.
 
 2005-10-06  Richard Henderson  <rth@redhat.com>
 
@@ -1000,8 +1007,8 @@
 2005-09-23  Fariborz Jahanian <fjahanian@apple.com>
 
 	PR target/23847
-        * config/rs6000/rs6000.c (rs6000_function_value): Parallel pattern
-        for __complex__ double in -mcpu=G5 mode.
+	* config/rs6000/rs6000.c (rs6000_function_value): Parallel pattern
+	for __complex__ double in -mcpu=G5 mode.
 
 2005-09-26  Sebastian Pop  <pop@cri.ensmp.fr>
 
@@ -1026,7 +1033,7 @@
 
 2005-09-26    Fariborz Jahanian <fjahanian@apple.com>
 
-        * combine.c (make_extraction): Check for valid use of subreg.
+	* combine.c (make_extraction): Check for valid use of subreg.
 
 2005-09-26  Uros Bizjak  <uros@kss-loka.si>
 
@@ -1170,10 +1177,10 @@
 
 2005-09-22  David Edelsohn  <edelsohn@gnu.org>
 
-        PR target/24007
-        * config/rs6000/rs6000.md (movsf_hardfloat): Ignore special
-        registers when choosing register preferences.
-        (movdf_hardfloat64): Same.
+	PR target/24007
+	* config/rs6000/rs6000.md (movsf_hardfloat): Ignore special
+	registers when choosing register preferences.
+	(movdf_hardfloat64): Same.
 
 2005-09-22  Andreas Krebbel  <krebbel1@de.ibm.com>
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 52012ebc9ccd8ff5aa82e4a6b29eea6d23ca11cb..b7d891e041e4531500e908954f1088023e0878d2 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1468,6 +1468,40 @@ gimplify_conversion (tree *expr_p)
   return GS_OK;
 }
 
+/* Gimplify a VAR_DECL or PARM_DECL.  Returns GS_OK if we expanded a 
+   DECL_VALUE_EXPR, and it's worth re-examining things.  */
+
+static enum gimplify_status
+gimplify_var_or_parm_decl (tree *expr_p)
+{
+  tree decl = *expr_p;
+
+  /* ??? If this is a local variable, and it has not been seen in any
+     outer BIND_EXPR, then it's probably the result of a duplicate
+     declaration, for which we've already issued an error.  It would
+     be really nice if the front end wouldn't leak these at all.
+     Currently the only known culprit is C++ destructors, as seen
+     in g++.old-deja/g++.jason/binding.C.  */
+  if (TREE_CODE (decl) == VAR_DECL
+      && !DECL_SEEN_IN_BIND_EXPR_P (decl)
+      && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
+      && decl_function_context (decl) == current_function_decl)
+    {
+      gcc_assert (errorcount || sorrycount);
+      return GS_ERROR;
+    }
+
+  /* If the decl is an alias for another expression, substitute it now.  */
+  if (DECL_HAS_VALUE_EXPR_P (decl))
+    {
+      *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
+      return GS_OK;
+    }
+
+  return GS_ALL_DONE;
+}
+
+
 /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
    node pointed to by EXPR_P.
 
@@ -1506,11 +1540,21 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
   /* We can handle anything that get_inner_reference can deal with.  */
   for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
     {
+    restart:
       /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs.  */
       if (TREE_CODE (*p) == INDIRECT_REF)
 	*p = fold_indirect_ref (*p);
-      if (!handled_component_p (*p))
+
+      if (handled_component_p (*p))
+	;
+      /* Expand DECL_VALUE_EXPR now.  In some cases that may expose
+	 additional COMPONENT_REFs.  */
+      else if ((TREE_CODE (*p) == VAR_DECL || TREE_CODE (*p) == PARM_DECL)
+	       && gimplify_var_or_parm_decl (p) == GS_OK)
+	goto restart;
+      else
 	break;
+	       
       VEC_safe_push (tree, heap, stack, *p);
     }
 
@@ -1592,8 +1636,11 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
 	}
     }
 
-  /* Step 2 is to gimplify the base expression.  */
-  tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval, fallback);
+  /* Step 2 is to gimplify the base expression.  Make sure lvalue is set
+     so as to match the min_lval predicate.  Failure to do so may result
+     in the creation of large aggregate temporaries.  */
+  tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
+			fallback | fb_lvalue);
   ret = MIN (ret, tret);
 
   /* And finally, the indices and operands to BIT_FIELD_REF.  During this
@@ -4371,36 +4418,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
 	  break;
 
 	case VAR_DECL:
-	  /* ??? If this is a local variable, and it has not been seen in any
-	     outer BIND_EXPR, then it's probably the result of a duplicate
-	     declaration, for which we've already issued an error.  It would
-	     be really nice if the front end wouldn't leak these at all.
-	     Currently the only known culprit is C++ destructors, as seen
-	     in g++.old-deja/g++.jason/binding.C.  */
-	  tmp = *expr_p;
-	  if (!TREE_STATIC (tmp) && !DECL_EXTERNAL (tmp)
-	      && decl_function_context (tmp) == current_function_decl
-	      && !DECL_SEEN_IN_BIND_EXPR_P (tmp))
-	    {
-	      gcc_assert (errorcount || sorrycount);
-	      ret = GS_ERROR;
-	      break;
-	    }
-	  /* FALLTHRU */
-
 	case PARM_DECL:
-	  tmp = *expr_p;
-
-	  /* If this is a local variable sized decl, it must be accessed
-	     indirectly.  Perform that substitution.  */
-	  if (DECL_HAS_VALUE_EXPR_P (tmp))
-	    {
-	      *expr_p = unshare_expr (DECL_VALUE_EXPR (tmp));
-	      ret = GS_OK;
-	      break;
-	    }
-
-	  ret = GS_ALL_DONE;
+	  ret = gimplify_var_or_parm_decl (expr_p);
 	  break;
 
 	case SSA_NAME: