From ba4d8f9d37bf11be3a98504812447cd9bbaad708 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Tue, 31 Mar 2009 10:23:44 +0000
Subject: [PATCH] re PR middle-end/23401 (Gimplifier produces too many
 temporaries)

2009-03-31  Richard Guenther  <rguenther@suse.de>

	PR middle-end/23401
	PR middle-end/27810
	* tree.h (DECL_GIMPLE_FORMAL_TEMP_P): Remove.
	(struct tree_decl_with_vis): Remove gimple_formal_temp member.
	* tree-eh.c (lower_eh_constructs_2): Move LHS assignment to
	a separate statement.
	* gimplify.c (pop_gimplify_context): Remove formal temp handling.
	(lookup_tmp_var): Likewise.
	(is_gimple_formal_tmp_or_call_rhs): Remove.
	(is_gimple_reg_or_call_rhs): Rename to ...
	(is_gimple_reg_rhs_or_call): ... this.
	(is_gimple_mem_or_call_rhs): Rename to ...
	(is_gimple_mem_rhs_or_call): ... this.
	(internal_get_tmp_var): Use is_gimple_reg_rhs_or_call.  Set
	DECL_GIMPLE_REG_P only if is_formal is true.
	(gimplify_compound_lval): Use is_gimple_reg.  Remove workaround
	for non-proper post-modify expression gimplification.
	(gimplify_self_mod_expr): For post-modify expressions gimplify
	the lvalue to a minimal lvalue.
	(rhs_predicate_for): Remove formal temp case.
	(gimplify_modify_expr_rhs): Likewise.
	(gimplify_addr_expr): Use is_gimple_reg.
	(gimplify_expr): Remove formal temp cases.
	(gimple_regimplify_operands): Likewise.
	* tree-ssa-pre.c (get_or_alloc_expr_for): Treat EXC_PTR_EXPR
	and FILTER_EXPR like constants.
	* gimple.c (walk_gimple_op): Fix val_only initialization, use
	is_gimple_reg.
	(is_gimple_formal_tmp_rhs): Remove.
	(is_gimple_reg_rhs): Remove special casing.
	(is_gimple_mem_rhs): Fix.
	(is_gimple_reg): Move DECL_GIMPLE_REG_P handling earlier.
	(is_gimple_formal_tmp_var): Remove.
	(is_gimple_formal_tmp_reg): Likewise.
	(is_gimple_min_lval): Allow invariant component ref parts.
	* gimple.h (is_gimple_formal_tmp_rhs, is_gimple_formal_tmp_var,
	is_gimple_formal_tmp_reg): Remove declarations.
	* tree-cfg.c (verify_expr): Verify that variables with address
	taken do not have DECL_GIMPLE_REG_P set.
	* tree-mudflap.c (mf_build_check_statement_for): Use
	force_gimple_operand instead of gimplify_expr.

	java/
	* java-gimplify.c (java_gimplify_expr): Do not manually gimplify
	the first operand of binary and comaprison expressions.

	* gcc.dg/tree-ssa/pr23401.c: New testcase.
	* gcc.dg/tree-ssa/pr27810.c: Likewise.

From-SVN: r145338
---
 gcc/ChangeLog                           |  44 ++++++++
 gcc/gimple.c                            |  74 +++----------
 gcc/gimple.h                            |   5 -
 gcc/gimplify.c                          | 137 ++++++++----------------
 gcc/java/ChangeLog                      |   5 +
 gcc/java/java-gimplify.c                |  20 ----
 gcc/testsuite/ChangeLog                 |   7 ++
 gcc/testsuite/gcc.dg/tree-ssa/pr23401.c |  24 +++++
 gcc/testsuite/gcc.dg/tree-ssa/pr27810.c |  18 ++++
 gcc/tree-cfg.c                          |   5 +
 gcc/tree-eh.c                           |  19 ++++
 gcc/tree-mudflap.c                      |  17 +--
 gcc/tree-ssa-pre.c                      |   4 +-
 gcc/tree.h                              |   8 +-
 14 files changed, 195 insertions(+), 192 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr27810.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 81886235bd6e..15a8228c6cf9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,47 @@
+2009-03-31  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/23401
+	PR middle-end/27810
+	* tree.h (DECL_GIMPLE_FORMAL_TEMP_P): Remove.
+	(struct tree_decl_with_vis): Remove gimple_formal_temp member.
+	* tree-eh.c (lower_eh_constructs_2): Move LHS assignment to
+	a separate statement.
+	* gimplify.c (pop_gimplify_context): Remove formal temp handling.
+	(lookup_tmp_var): Likewise.
+	(is_gimple_formal_tmp_or_call_rhs): Remove.
+	(is_gimple_reg_or_call_rhs): Rename to ...
+	(is_gimple_reg_rhs_or_call): ... this.
+	(is_gimple_mem_or_call_rhs): Rename to ...
+	(is_gimple_mem_rhs_or_call): ... this.
+	(internal_get_tmp_var): Use is_gimple_reg_rhs_or_call.  Set
+	DECL_GIMPLE_REG_P only if is_formal is true.
+	(gimplify_compound_lval): Use is_gimple_reg.  Remove workaround
+	for non-proper post-modify expression gimplification.
+	(gimplify_self_mod_expr): For post-modify expressions gimplify
+	the lvalue to a minimal lvalue.
+	(rhs_predicate_for): Remove formal temp case.
+	(gimplify_modify_expr_rhs): Likewise.
+	(gimplify_addr_expr): Use is_gimple_reg.
+	(gimplify_expr): Remove formal temp cases.
+	(gimple_regimplify_operands): Likewise.
+	* tree-ssa-pre.c (get_or_alloc_expr_for): Treat EXC_PTR_EXPR
+	and FILTER_EXPR like constants.
+	* gimple.c (walk_gimple_op): Fix val_only initialization, use
+	is_gimple_reg.
+	(is_gimple_formal_tmp_rhs): Remove.
+	(is_gimple_reg_rhs): Remove special casing.
+	(is_gimple_mem_rhs): Fix.
+	(is_gimple_reg): Move DECL_GIMPLE_REG_P handling earlier.
+	(is_gimple_formal_tmp_var): Remove.
+	(is_gimple_formal_tmp_reg): Likewise.
+	(is_gimple_min_lval): Allow invariant component ref parts.
+	* gimple.h (is_gimple_formal_tmp_rhs, is_gimple_formal_tmp_var,
+	is_gimple_formal_tmp_reg): Remove declarations.
+	* tree-cfg.c (verify_expr): Verify that variables with address
+	taken do not have DECL_GIMPLE_REG_P set.
+	* tree-mudflap.c (mf_build_check_statement_for): Use
+	force_gimple_operand instead of gimplify_expr.
+
 2009-03-31  Ayal Zaks  <zaks@il.ibm.com>
 
 	* modulo-sched.c (sms_schedule_by_order): Pass the actual
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 90de9b3ebc56..a1dd6a750723 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1380,7 +1380,8 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
       /* Walk the RHS operands.  A formal temporary LHS may use a
 	 COMPONENT_REF RHS.  */
       if (wi)
-	wi->val_only = !is_gimple_formal_tmp_var (gimple_assign_lhs (stmt));
+	wi->val_only = !is_gimple_reg (gimple_assign_lhs (stmt))
+                       || !gimple_assign_single_p (stmt);
 
       for (i = 1; i < gimple_num_ops (stmt); i++)
 	{
@@ -2559,37 +2560,13 @@ is_gimple_operand (const_tree op)
   return op && get_gimple_rhs_class (TREE_CODE (op)) == GIMPLE_SINGLE_RHS;
 }
 
-
-/* Return true if T is a GIMPLE RHS for an assignment to a temporary.  */
-
-bool
-is_gimple_formal_tmp_rhs (tree t)
-{
-  if (is_gimple_lvalue (t) || is_gimple_val (t))
-    return true;
-
-  return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
-}
-
 /* Returns true iff T is a valid RHS for an assignment to a renamed
    user -- or front-end generated artificial -- variable.  */
 
 bool
 is_gimple_reg_rhs (tree t)
 {
-  /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
-     and the LHS is a user variable, then we need to introduce a formal
-     temporary.  This way the optimizers can determine that the user
-     variable is only modified if evaluation of the RHS does not throw.
-
-     Don't force a temp of a non-renamable type; the copy could be
-     arbitrarily expensive.  Instead we will generate a VDEF for
-     the assignment.  */
-
-  if (is_gimple_reg_type (TREE_TYPE (t)) && tree_could_throw_p (t))
-    return false;
-
-  return is_gimple_formal_tmp_rhs (t);
+  return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
 }
 
 /* Returns true iff T is a valid RHS for an assignment to an un-renamed
@@ -2603,7 +2580,7 @@ is_gimple_mem_rhs (tree t)
   if (is_gimple_reg_type (TREE_TYPE (t)))
     return is_gimple_val (t);
   else
-    return is_gimple_formal_tmp_rhs (t);
+    return is_gimple_val (t) || is_gimple_lvalue (t);
 }
 
 /*  Return true if T is a valid LHS for a GIMPLE assignment expression.  */
@@ -2895,6 +2872,12 @@ is_gimple_reg (tree t)
   if (!is_gimple_variable (t))
     return false;
 
+  /* Complex and vector values must have been put into SSA-like form.
+     That is, no assignments to the individual components.  */
+  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+    return DECL_GIMPLE_REG_P (t);
+
   if (!is_gimple_reg_type (TREE_TYPE (t)))
     return false;
 
@@ -2921,45 +2904,10 @@ is_gimple_reg (tree t)
   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
     return false;
 
-  /* Complex and vector values must have been put into SSA-like form.
-     That is, no assignments to the individual components.  */
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    return DECL_GIMPLE_REG_P (t);
-
   return true;
 }
 
 
-/* Returns true if T is a GIMPLE formal temporary variable.  */
-
-bool
-is_gimple_formal_tmp_var (tree t)
-{
-  if (TREE_CODE (t) == SSA_NAME)
-    return true;
-
-  return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t);
-}
-
-/* Returns true if T is a GIMPLE formal temporary register variable.  */
-
-bool
-is_gimple_formal_tmp_reg (tree t)
-{
-  /* The intent of this is to get hold of a value that won't change.
-     An SSA_NAME qualifies no matter if its of a user variable or not.  */
-  if (TREE_CODE (t) == SSA_NAME)
-    return true;
-
-  /* We don't know the lifetime characteristics of user variables.  */
-  if (!is_gimple_formal_tmp_var (t))
-    return false;
-
-  /* Finally, it must be capable of being placed in a register.  */
-  return is_gimple_reg (t);
-}
-
 /* Return true if T is a GIMPLE variable whose address is not needed.  */
 
 bool
@@ -3006,6 +2954,8 @@ is_gimple_asm_val (tree t)
 bool
 is_gimple_min_lval (tree t)
 {
+  if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
+    return false;
   return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF);
 }
 
diff --git a/gcc/gimple.h b/gcc/gimple.h
index df9bccdc3cdc..b482c1d607df 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -859,10 +859,6 @@ extern bool is_gimple_stmt (tree);
 extern bool is_gimple_reg_type (tree);
 /* Returns true iff T is a scalar register variable.  */
 extern bool is_gimple_reg (tree);
-/* Returns true if T is a GIMPLE temporary variable, false otherwise.  */
-extern bool is_gimple_formal_tmp_var (tree);
-/* Returns true if T is a GIMPLE temporary register variable.  */
-extern bool is_gimple_formal_tmp_reg (tree);
 /* Returns true iff T is any sort of variable.  */
 extern bool is_gimple_variable (tree);
 /* Returns true iff T is any sort of symbol.  */
@@ -894,7 +890,6 @@ extern bool is_gimple_asm_val (tree);
 /* Returns true iff T is a valid rhs for a MODIFY_EXPR where the LHS is a
    GIMPLE temporary, a renamed user variable, or something else,
    respectively.  */
-extern bool is_gimple_formal_tmp_rhs (tree);
 extern bool is_gimple_reg_rhs (tree);
 extern bool is_gimple_mem_rhs (tree);
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index bd82051d1589..515c58ed57e9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -214,16 +214,12 @@ void
 pop_gimplify_context (gimple body)
 {
   struct gimplify_ctx *c = gimplify_ctxp;
-  tree t;
 
   gcc_assert (c && (c->bind_expr_stack == NULL
 		    || VEC_empty (gimple, c->bind_expr_stack)));
   VEC_free (gimple, heap, c->bind_expr_stack);
   gimplify_ctxp = c->prev_context;
 
-  for (t = c->temps; t ; t = TREE_CHAIN (t))
-    DECL_GIMPLE_FORMAL_TEMP_P (t) = 0;
-
   if (body)
     declare_vars (c->temps, body, false);
   else
@@ -609,9 +605,6 @@ lookup_tmp_var (tree val, bool is_formal)
 	}
     }
 
-  if (is_formal)
-    DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1;
-
   return ret;
 }
 
@@ -622,32 +615,10 @@ lookup_tmp_var (tree val, bool is_formal)
    gimplify_modify_expr.  */
 
 static bool
-is_gimple_formal_tmp_or_call_rhs (tree t)
+is_gimple_reg_rhs_or_call (tree t)
 {
-  return TREE_CODE (t) == CALL_EXPR || is_gimple_formal_tmp_rhs (t);
-}
-
-/* Returns true iff T is a valid RHS for an assignment to a renamed
-   user -- or front-end generated artificial -- variable.  */
-
-static bool
-is_gimple_reg_or_call_rhs (tree t)
-{
-  /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
-     and the LHS is a user variable, then we need to introduce a formal
-     temporary.  This way the optimizers can determine that the user
-     variable is only modified if evaluation of the RHS does not throw.
-
-     Don't force a temp of a non-renamable type; the copy could be
-     arbitrarily expensive.  Instead we will generate a VDEF for
-     the assignment.  */
-
-  if (is_gimple_reg_type (TREE_TYPE (t))
-      && ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
-	  || tree_could_throw_p (t)))
-    return false;
-
-  return is_gimple_formal_tmp_or_call_rhs (t);
+  return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
+	  || TREE_CODE (t) == CALL_EXPR);
 }
 
 /* Return true if T is a valid memory RHS or a CALL_EXPR.  Note that
@@ -655,28 +626,18 @@ is_gimple_reg_or_call_rhs (tree t)
    rationale for this in gimplify_modify_expr.  */
 
 static bool
-is_gimple_mem_or_call_rhs (tree t)
+is_gimple_mem_rhs_or_call (tree t)
 {
   /* If we're dealing with a renamable type, either source or dest must be
      a renamed variable.  */
   if (is_gimple_reg_type (TREE_TYPE (t)))
     return is_gimple_val (t);
   else
-    return is_gimple_formal_tmp_or_call_rhs (t);
+    return (is_gimple_val (t) || is_gimple_lvalue (t)
+	    || TREE_CODE (t) == CALL_EXPR);
 }
 
-
-/* Returns a formal temporary variable initialized with VAL.  PRE_P is as
-   in gimplify_expr.  Only use this function if:
-
-   1) The value of the unfactored expression represented by VAL will not
-      change between the initialization and use of the temporary, and
-   2) The temporary will not be otherwise modified.
-
-   For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
-   and #2 means it is inappropriate for && temps.
-
-   For other cases, use get_initialized_tmp_var instead.  */
+/* Helper for get_formal_tmp_var and get_initialized_tmp_var.  */
 
 static tree
 internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
@@ -686,7 +647,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
 
   /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
      can create an INIT_EXPR and convert it into a GIMPLE_CALL below.  */
-  gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_or_call_rhs,
+  gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
 		 fb_rvalue);
 
   t = lookup_tmp_var (val, is_formal);
@@ -707,11 +668,11 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
 	      SET_DECL_RESTRICT_BASE (t, u);
 	    }
 	}
-    }
 
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (t) = 1;
+      if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+	  || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+	DECL_GIMPLE_REG_P (t) = 1;
+    }
 
   mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
 
@@ -735,9 +696,17 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
   return t;
 }
 
-/* Returns a formal temporary variable initialized with VAL.  PRE_P
-   points to a sequence where side-effects needed to compute VAL should be
-   stored.  */
+/* Returns a formal temporary variable initialized with VAL.  PRE_P is as
+   in gimplify_expr.  Only use this function if:
+
+   1) The value of the unfactored expression represented by VAL will not
+      change between the initialization and use of the temporary, and
+   2) The temporary will not be otherwise modified.
+
+   For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
+   and #2 means it is inappropriate for && temps.
+
+   For other cases, use get_initialized_tmp_var instead.  */
 
 tree
 get_formal_tmp_var (tree val, gimple_seq *pre_p)
@@ -2006,7 +1975,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 		{
 		  TREE_OPERAND (t, 2) = low;
 		  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
-					post_p, is_gimple_formal_tmp_reg,
+					post_p, is_gimple_reg,
 					fb_rvalue);
 		  ret = MIN (ret, tret);
 		}
@@ -2026,7 +1995,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 		{
 		  TREE_OPERAND (t, 3) = elmt_size;
 		  tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
-					post_p, is_gimple_formal_tmp_reg,
+					post_p, is_gimple_reg,
 					fb_rvalue);
 		  ret = MIN (ret, tret);
 		}
@@ -2049,7 +2018,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 		{
 		  TREE_OPERAND (t, 2) = offset;
 		  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
-					post_p, is_gimple_formal_tmp_reg,
+					post_p, is_gimple_reg,
 					fb_rvalue);
 		  ret = MIN (ret, tret);
 		}
@@ -2072,19 +2041,11 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
       if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
 	{
-	  /* Gimplify the dimension.
-	     Temporary fix for gcc.c-torture/execute/20040313-1.c.
-	     Gimplify non-constant array indices into a temporary
-	     variable.
-	     FIXME - The real fix is to gimplify post-modify
-	     expressions into a minimal gimple lvalue.  However, that
-	     exposes bugs in alias analysis.  The alias analyzer does
-	     not handle &PTR->FIELD very well.  Will fix after the
-	     branch is merged into mainline (dnovillo 2004-05-03).  */
+	  /* Gimplify the dimension.  */
 	  if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
 	    {
 	      tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
-				    is_gimple_formal_tmp_reg, fb_rvalue);
+				    is_gimple_val, fb_rvalue);
 	      ret = MIN (ret, tret);
 	    }
 	}
@@ -2176,9 +2137,18 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   rhs = TREE_OPERAND (*expr_p, 1);
 
   /* For postfix operator, we evaluate the LHS to an rvalue and then use
-     that as the result value and in the postqueue operation.  */
+     that as the result value and in the postqueue operation.  We also
+     make sure to make lvalue a minimal lval, see
+     gcc.c-torture/execute/20040313-1.c for an example where this matters.  */
   if (postfix)
     {
+      if (!is_gimple_min_lval (lvalue))
+	{
+	  mark_addressable (lvalue);
+	  lvalue = build_fold_addr_expr (lvalue);
+	  gimplify_expr (&lvalue, pre_p, post_p, is_gimple_val, fb_rvalue);
+	  lvalue = build_fold_indirect_ref (lvalue);
+	}
       ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
       if (ret == GS_ERROR)
 	return ret;
@@ -3448,12 +3418,10 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
 gimple_predicate
 rhs_predicate_for (tree lhs)
 {
-  if (is_gimple_formal_tmp_var (lhs))
-    return is_gimple_formal_tmp_or_call_rhs;
-  else if (is_gimple_reg (lhs))
-    return is_gimple_reg_or_call_rhs;
+  if (is_gimple_reg (lhs))
+    return is_gimple_reg_rhs_or_call;
   else
-    return is_gimple_mem_or_call_rhs;
+    return is_gimple_mem_rhs_or_call;
 }
 
 /* Gimplify a C99 compound literal expression.  This just means adding
@@ -4120,11 +4088,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
 		     || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
 	      /* Don't force regs into memory.  */
 	      use_target = false;
-	    else if (TREE_CODE (*to_p) == VAR_DECL
-		     && DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
-	      /* Don't use the original target if it's a formal temp; we
-		 don't want to take their addresses.  */
-	      use_target = false;
 	    else if (TREE_CODE (*expr_p) == INIT_EXPR)
 	      /* It's OK to use the target directly if it's being
 		 initialized. */
@@ -4644,7 +4607,7 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 	 This mostly happens if the frontend passed us something that
 	 it could not mark addressable yet, like a fortran
 	 pass-by-reference parameter (int) floatvar.  */
-      if (is_gimple_formal_tmp_var (TREE_OPERAND (expr, 0)))
+      if (is_gimple_reg (TREE_OPERAND (expr, 0)))
 	TREE_OPERAND (expr, 0)
 	  = get_initialized_tmp_var (TREE_OPERAND (expr, 0), pre_p, post_p);
 
@@ -6316,16 +6279,12 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   if (gimple_test_f == is_gimple_reg)
     gcc_assert (fallback & (fb_rvalue | fb_lvalue));
   else if (gimple_test_f == is_gimple_val
-           || gimple_test_f == is_gimple_formal_tmp_rhs
-           || gimple_test_f == is_gimple_formal_tmp_or_call_rhs
-           || gimple_test_f == is_gimple_formal_tmp_reg
-           || gimple_test_f == is_gimple_formal_tmp_var
            || gimple_test_f == is_gimple_call_addr
            || gimple_test_f == is_gimple_condexpr
            || gimple_test_f == is_gimple_mem_rhs
-           || gimple_test_f == is_gimple_mem_or_call_rhs
+           || gimple_test_f == is_gimple_mem_rhs_or_call
            || gimple_test_f == is_gimple_reg_rhs
-           || gimple_test_f == is_gimple_reg_or_call_rhs
+           || gimple_test_f == is_gimple_reg_rhs_or_call
            || gimple_test_f == is_gimple_asm_val)
     gcc_assert (fallback & fb_rvalue);
   else if (gimple_test_f == is_gimple_min_lval
@@ -7128,7 +7087,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
       *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
     }
-  else if ((fallback & fb_rvalue) && is_gimple_formal_tmp_or_call_rhs (*expr_p))
+  else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
     {
       /* An rvalue will do.  Assign the gimplified expression into a
 	 new temporary TMP and replace the original expression with
@@ -7143,9 +7102,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	*expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
       else
 	*expr_p = get_formal_tmp_var (*expr_p, pre_p);
-
-      if (TREE_CODE (*expr_p) != SSA_NAME)
-	DECL_GIMPLE_FORMAL_TEMP_P (*expr_p) = 1;
     }
   else
     {
@@ -7597,7 +7553,7 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
       lhs = gimple_get_lhs (stmt);
       /* If the LHS changed it in a way that requires a simple RHS,
 	 create temporary.  */
-      if (lhs && !is_gimple_formal_tmp_var (lhs))
+      if (lhs && !is_gimple_reg (lhs))
 	{
 	  bool need_temp = false;
 
@@ -7646,7 +7602,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
 	    {
 	      tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
 
-	      DECL_GIMPLE_FORMAL_TEMP_P (temp) = 1;
 	      if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
 		  || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
 		DECL_GIMPLE_REG_P (temp) = 1;
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index a72a2f947019..62c76a77c4f3 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,8 @@
+2009-03-31  Richard Guenther  <rguenther@suse.de>
+
+	* java-gimplify.c (java_gimplify_expr): Do not manually gimplify
+	the first operand of binary and comaprison expressions.
+
 2009-03-30  Joseph Myers  <joseph@codesourcery.com>
 
 	PR rtl-optimization/323
diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c
index a43e67e5fec3..e2ad02b697a1 100644
--- a/gcc/java/java-gimplify.c
+++ b/gcc/java/java-gimplify.c
@@ -96,26 +96,6 @@ java_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
       gcc_unreachable ();
 
     default:
-      /* Java insists on strict left-to-right evaluation of expressions.
-	 A problem may arise if a variable used in the LHS of a binary
-	 operation is altered by an assignment to that value in the RHS
-	 before we've performed the operation.  So, we always copy every
-	 LHS to a temporary variable.  
-
-	 FIXME: Are there any other cases where we should do this?
-	 Parameter lists, maybe?  Or perhaps that's unnecessary because
-	 the front end already generates SAVE_EXPRs.  */
-
-      if (TREE_CODE_CLASS (code) == tcc_binary
-	  || TREE_CODE_CLASS (code) == tcc_comparison)
-	{
-	  enum gimplify_status stat 
-	    = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-			     is_gimple_formal_tmp_var, fb_rvalue);
-	  if (stat == GS_ERROR)
-	    return stat;
-	}
-
       return GS_UNHANDLED;
     }
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aadb0da5e339..c21f1074cfb6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-03-31  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/23401
+	PR middle-end/27810
+	* gcc.dg/tree-ssa/pr23401.c: New testcase.
+	* gcc.dg/tree-ssa/pr27810.c: Likewise.
+
 2009-03-30  Steven G. Kargl  <kargls@comcast.net>
 
 	PR fortran/38389
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
new file mode 100644
index 000000000000..1d30ac7519f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+struct f
+{
+  struct {
+      int i;
+  } ff[10];
+};
+
+struct f g;
+int ffff(int i)
+{
+  int t1 = 0;
+  int i1 = g.ff[t1].i;
+  int i2 = g.ff[i].i;
+  return i1 + i2;
+}
+
+/* We should not use extra temporaries apart from for i1 + i2.  */
+
+/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
new file mode 100644
index 000000000000..c7da3bd5d06b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int bar (int);
+
+int qqq (int a)
+{
+    int result;
+    result = bar (a);
+    return result;
+}
+
+/* We should not use an extra temporary for the result of the
+   function call.  */
+
+/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 9c5b2e6c58ca..66f121836cb3 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2886,6 +2886,11 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 	    error ("address taken, but ADDRESSABLE bit not set");
 	    return x;
 	  }
+	if (DECL_GIMPLE_REG_P (x))
+	  {
+	    error ("DECL_GIMPLE_REG_P set on a variable with address taken");
+	    return x;
+	  }
 
 	break;
       }
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index f55a4172b104..1d9a9bdac362 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1823,6 +1823,25 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
     {
     case GIMPLE_CALL:
     case GIMPLE_ASSIGN:
+      /* If the stmt can throw use a new temporary for the assignment
+         to a LHS.  This makes sure the old value of the LHS is
+	 available on the EH edge.  */
+      if (stmt_could_throw_p (stmt)
+	  && gimple_has_lhs (stmt)
+	  && !tree_could_throw_p (gimple_get_lhs (stmt))
+	  && is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))))
+	{
+	  tree lhs = gimple_get_lhs (stmt);
+	  tree tmp = create_tmp_var (TREE_TYPE (lhs), NULL);
+	  gimple s = gimple_build_assign (lhs, tmp);
+	  gimple_set_location (s, gimple_location (stmt));
+	  gimple_set_block (s, gimple_block (stmt));
+	  gimple_set_lhs (stmt, tmp);
+	  if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
+	      || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
+	    DECL_GIMPLE_REG_P (tmp) = 1;
+	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
+	}
       /* Look for things that can throw exceptions, and record them.  */
       if (state->cur_region && stmt_could_throw_p (stmt))
 	{
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
index 831fcc1791a8..dae12874dad6 100644
--- a/gcc/tree-mudflap.c
+++ b/gcc/tree-mudflap.c
@@ -503,7 +503,7 @@ mf_build_check_statement_for (tree base, tree limit,
   tree mf_elem;
   tree mf_limit;
   gimple g;
-  gimple_seq seq;
+  gimple_seq seq, stmts;
 
   /* We first need to split the current basic block, and start altering
      the CFG.  This allows us to insert the statements we're about to
@@ -553,14 +553,16 @@ mf_build_check_statement_for (tree base, tree limit,
   /* Build: __mf_base = (uintptr_t) <base address expression>.  */
   seq = gimple_seq_alloc ();
   t = fold_convert (mf_uintptr_type, unshare_expr (base));
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_assign (mf_base, t);
   gimple_set_location (g, location);
   gimple_seq_add_stmt (&seq, g);
 
   /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
   t = fold_convert (mf_uintptr_type, unshare_expr (limit));
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_assign (mf_limit, t);
   gimple_set_location (g, location);
   gimple_seq_add_stmt (&seq, g);
@@ -577,7 +579,8 @@ mf_build_check_statement_for (tree base, tree limit,
               TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
               mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
   t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_assign (mf_elem, t);
   gimple_set_location (g, location);
   gimple_seq_add_stmt (&seq, g);
@@ -622,7 +625,8 @@ mf_build_check_statement_for (tree base, tree limit,
      result of the evaluation of 't' in a temporary variable which we
      can use as the condition for the conditional jump.  */
   t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
-  gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
+  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
   g = gimple_build_assign  (cond, t);
   gimple_set_location (g, location);
@@ -663,7 +667,8 @@ mf_build_check_statement_for (tree base, tree limit,
   v = fold_build2 (PLUS_EXPR, integer_type_node,
 		   fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
 		   integer_one_node);
-  gimplify_expr (&v, &seq, &seq, is_gimple_mem_rhs, fb_rvalue);
+  v = force_gimple_operand (v, &stmts, true, NULL_TREE);
+  gimple_seq_add_seq (&seq, stmts);
   g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u);
   gimple_seq_add_stmt (&seq, g);
 
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 9d06a8a3f297..267c2fcfea22 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1051,7 +1051,9 @@ get_or_alloc_expr_for (tree t)
 {
   if (TREE_CODE (t) == SSA_NAME)
     return get_or_alloc_expr_for_name (t);
-  else if (is_gimple_min_invariant (t))
+  else if (is_gimple_min_invariant (t)
+	   || TREE_CODE (t) == EXC_PTR_EXPR
+	   || TREE_CODE (t) == FILTER_EXPR)
     return get_or_alloc_expr_for_constant (t);
   else
     {
diff --git a/gcc/tree.h b/gcc/tree.h
index 830852de8b56..1a83c2505da5 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2928,11 +2928,6 @@ struct tree_parm_decl GTY(())
   /* Used to indicate that this DECL has weak linkage.  */
 #define DECL_WEAK(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.weak_flag)
 
-/* Internal to the gimplifier.  Indicates that the value is a formal
-   temporary controlled by the gimplifier.  */
-#define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
-  DECL_WITH_VIS_CHECK (DECL)->decl_with_vis.gimple_formal_temp
-
 /* Used to indicate that the DECL is a dllimport.  */
 #define DECL_DLLIMPORT_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
 
@@ -3044,7 +3039,6 @@ struct tree_decl_with_vis GTY(())
  unsigned thread_local:1;
  unsigned common_flag:1;
  unsigned in_text_section : 1;
- unsigned gimple_formal_temp : 1;
  unsigned dllimport_flag : 1;
  unsigned based_on_restrict_p : 1;
  /* Used by C++.  Might become a generic decl flag.  */
@@ -3062,7 +3056,7 @@ struct tree_decl_with_vis GTY(())
 
  /* Belongs to VAR_DECL exclusively.  */
  ENUM_BITFIELD(tls_model) tls_model : 3;
- /* 12 unused bits. */
+ /* 13 unused bits. */
 };
 
 /* In a VAR_DECL that's static,
-- 
GitLab