public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Eliminate TREE_INVARIANT
@ 2008-04-05  7:36 Paolo Bonzini
  2008-04-05  7:40 ` Eric Botcazou
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-05  7:36 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1509 bytes --]

TREE_INVARIANT is read very rarely, and it seems to me that it is 
treated as TREE_CONSTANT (x) || TREE_CODE (x) == SAVE_EXPR.  So that's 
what this patch does.

There's one exception in save_expr, where we want to not wrap invariant 
addresses: for this I used is_gimple_invariant_address after modifying 
it to not crash for front-end specific trees (this is the new function 
invariant_addr_p in tree.c; functions in tree.c don't use is_* apparently).

I added another predicate is_gimple_address that is verified by the 
GIMPLE verifier, that crashed when is_gimple_invariant_address would 
crash, so that we are no less lenient WRT invalid GIMPLE.  Actually we 
perform *more* checking, because previously is_gimple_invariant_address 
would not reach the final switch (containing the call to 
gcc_unreachable) if it determined the address not to be invariant.

The sheer amount of eliminated lines is not huge, but it removes the 
need for the front-ends to set a flag that is used rarely and actually 
is just a cache of other information.

Bootstrapped/regtested i686-pc-linux-gnu, will redo it with Ada before 
committing.  No regression, and older versions did have them (for 
example, I got both pessimizations in memcpy->VIEW_CONVERT_EXPR folding, 
or crashes in template processing when the C++ front-end tried passing 
language-specific trees to save_expr).  So it seems that these paths are 
stressed quite heavily, and I'm confident that this patch will not 
introduce regressions.

Ok?

Paolo

[-- Attachment #2: kill-tree-invariant.patch --]
[-- Type: text/plain, Size: 46588 bytes --]

2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* tree-gimple.c (is_gimple_address): New from...
	(is_gimple_invariant_address): ... this one.
	(is_gimple_formal_tmp_rhs): Use it.
	* tree-gimple.h (is_gimple_address): New prototype replacing...
	(is_gimple_invariant_address): ... this one.
	* tree-cfg.c (verify_expr): Don't verify TREE_INVARIANT.
	Use is_gimple_address.
	* tree.c (make_node_stat): Don't set TREE_INVARIANT.
	(build_string): Likewise.
	(invariant_addr_p): New, from is_gimple_invariant_address.
	(save_expr): Use invariant_addr_p or TREE_CONSTANT.
	(skip_simple_arithmetic): Likewise, also check for SAVE_EXPRs.
	(stabilize_reference_1): Check TREE_CONSTANT, other invariant
	things are already wrapped into SAVE_EXPR.
	(recompute_tree_invariant_for_addr_expr): Don't update TREE_INVARIANT,
	simplify.
	(build1_stat): Drop code to compute TREE_INVARIANT.
	(build2_stat): Drop code to compute TREE_INVARIANT.
	(build3_stat): Drop code to compute TREE_INVARIANT.
	(build4_stat): Drop code to compute TREE_INVARIANT.
	(build5_stat): Drop code to compute TREE_INVARIANT.
	(build7_stat): Drop code to compute TREE_INVARIANT.
	(merge_dllimport_decl_attributes): Don't mention TREE_INVARIANT.
	* tree.h (struct tree_base): Remove invariant_flag.
	(TREE_INVARIANT): Remove.
	* builtins.c (build_string_literal): Don't set TREE_INVARIANT.
	(fold_builtin_expect): Check TREE_CONSTANT.
	* tree-ssa-ccp.c (fold_stmt_r): Adjust comment.
	* c-tree.h (c_expr_to_decl): Drop third parameter.
	* c-typeck.c (build_external_ref): Don't set TREE_INVARIANT.
	(build_c_cast): Don't set TREE_INVARIANT.
	(pop_init_level): Don't set TREE_INVARIANT.
	(c_objc_common_truthvalue_conversion): Don't set TREE_INVARIANT.
	* gimplify.c (gimplify_init_ctor_preeval): Add assertion, test
	TREE_CONSTANT.
	(gimplify_init_constructor): Don't set TREE_INVARIANT.
	(gimplify_addr_expr): Adjust comment.
	* tree-mudflap.c (mf_build_string):
	* print-tree.c (print_node): Don't print TREE_INVARIANT.
	* tree-nested.c (convert_nonlocal_reference): Adjust comment.
	* c-common.c (fix_string_type): Don't set TREE_INVARIANT.
	* langhooks-def.h (lhd_expr_to_decl): Drop third parameter.
	* langhooks.c (lhd_expr_to_decl): Drop third parameter.
	* langhooks.h (struct lang_hooks): Drop third parameter from
	expr_to_decl.

java:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* class.c (build_utf8_ref): Don't set TREE_INVARIANT.
	(build_classdollar_field): Don't set TREE_INVARIANT.
	(get_dispatch_table): Don't set TREE_INVARIANT.
	(make_class_data): Don't set TREE_INVARIANT.
	(build_symbol_entry): Don't set TREE_INVARIANT.
	(emit_symbol_table): Don't set TREE_INVARIANT.
	* constants.c (build_constant_data_ref): Don't set TREE_INVARIANT.
	(build_ref_from_constant_pool): Don't set TREE_INVARIANT.
	* resource.c (compile_resource_data): Don't set TREE_INVARIANT.
	* expr.c (cache_cpool_data_ref): Don't set TREE_INVARIANT.

objc:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* objc-act.c (objc_build_string_object): Don't set TREE_INVARIANT.

cp:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* typeck.c (get_member_function_from_ptrfunc): Don't set TREE_INVARIANT.
	(build_ptrmemfunc1): Don't set TREE_INVARIANT.
	* init.c (build_zero_init): Don't set TREE_INVARIANT.
	* class.c (build_base_path): Don't set TREE_INVARIANT.
	(build_vtbl_ref_1): Don't set TREE_INVARIANT.
	(build_vtbl_initializer): Don't set TREE_INVARIANT.
	* decl.c (build_enumerator): Don't set TREE_INVARIANT.
	* rtti.c (tinfo_base_init): Don't set TREE_INVARIANT.
	(generic_initializer): Don't set TREE_INVARIANT.
	(ptr_initializer): Don't set TREE_INVARIANT.
	(ptm_initializer): Don't set TREE_INVARIANT.
	(class_initializer): Don't set TREE_INVARIANT.
	* typeck2.c (process_init_constructor): Don't set TREE_INVARIANT.
	* pt.c (push_inline_template_parms_recursive): Don't set TREE_INVARIANT.
	(build_template_parm_index): Don't set TREE_INVARIANT.
	(reduce_template_parm_level): Don't set TREE_INVARIANT.
	(process_template_parm): Don't set TREE_INVARIANT.

ada:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* trans.c (Attribute_to_gnu): Don't set TREE_INVARIANT.
	(call_to_gnu): Don't set TREE_INVARIANT.
	* utils2.c (gnat_build_constructor): Don't set TREE_INVARIANT.

fortran:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* trans-expr.c (gfc_conv_structure): Don't set TREE_INVARIANT.
	* trans-array.c (gfc_build_null_descriptor): Don't set TREE_INVARIANT.
	(gfc_trans_array_constructor_value): Don't set TREE_INVARIANT.
	(gfc_build_constant_array_constructor): Don't set TREE_INVARIANT.
	(gfc_conv_array_initializer): Don't set TREE_INVARIANT.
	* trans-common.c (get_init_field): Don't set TREE_INVARIANT.
	(create_common): Don't set TREE_INVARIANT.
	* trans-stmt.c (gfc_trans_character_select): Don't set TREE_INVARIANT.
	* trans-decl.c (gfc_generate_function_code): Don't set TREE_INVARIANT.


Index: tree.c
===================================================================
--- tree.c	(revision 133899)
+++ tree.c	(working copy)
@@ -621,7 +621,6 @@ make_node_stat (enum tree_code code MEM_
 
     case tcc_constant:
       TREE_CONSTANT (t) = 1;
-      TREE_INVARIANT (t) = 1;
       break;
 
     case tcc_expression:
@@ -1192,7 +1191,6 @@ build_string (int len, const char *str)
   memset (s, 0, sizeof (struct tree_common));
   TREE_SET_CODE (s, STRING_CST);
   TREE_CONSTANT (s) = 1;
-  TREE_INVARIANT (s) = 1;
   TREE_STRING_LENGTH (s) = len;
   memcpy (s->string.str, str, len);
   s->string.str[len] = '\0';
@@ -2057,6 +2055,75 @@ staticp (tree arg)
     }
 }
 \f
+/* Return true if T is an invariant address.  */
+
+bool
+invariant_addr_p (const_tree t)
+{
+  tree op;
+
+  if (TREE_CODE (t) != ADDR_EXPR)
+    return false;
+
+  op = TREE_OPERAND (t, 0);
+  while (handled_component_p (op))
+    {
+      switch (TREE_CODE (op))
+	{
+	case ARRAY_REF:
+	case ARRAY_RANGE_REF:
+	  if (!is_gimple_constant (TREE_OPERAND (op, 1))
+	      || TREE_OPERAND (op, 2) != NULL_TREE
+	      || TREE_OPERAND (op, 3) != NULL_TREE)
+	    return false;
+	  break;
+
+	case COMPONENT_REF:
+	  if (TREE_OPERAND (op, 2) != NULL_TREE)
+	    return false;
+	  break;
+
+	default:;
+	}
+      op = TREE_OPERAND (op, 0);
+    }
+
+  if (CONSTANT_CLASS_P (op))
+    return true;
+
+  if (INDIRECT_REF_P (op))
+    return false;
+
+  switch (TREE_CODE (op))
+    {
+    case PARM_DECL:
+    case RESULT_DECL:
+    case LABEL_DECL:
+    case FUNCTION_DECL:
+      return true;
+
+    case VAR_DECL:
+      if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+	   && ! DECL_DLLIMPORT_P (op))
+	  || DECL_THREAD_LOCAL_P (op)
+	  || DECL_CONTEXT (op) == current_function_decl
+	  || decl_function_context (op) == current_function_decl)
+	return true;
+      break;
+
+    case CONST_DECL:
+      if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
+	  || decl_function_context (op) == current_function_decl)
+	return true;
+      break;
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
 /* Wrap a SAVE_EXPR around EXPR, if appropriate.
    Do this to any expression which may be used in more than one place,
    but must be evaluated only once.
@@ -2092,8 +2159,9 @@ save_expr (tree expr)
      literal node.  */
   inner = skip_simple_arithmetic (t);
 
-  if (TREE_INVARIANT (inner)
+  if (TREE_CONSTANT (inner)
       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
+      || (TREE_CODE (inner) == ADDR_EXPR && invariant_addr_p (inner))
       || TREE_CODE (inner) == SAVE_EXPR
       || TREE_CODE (inner) == ERROR_MARK)
     return t;
@@ -2116,7 +2184,6 @@ save_expr (tree expr)
      value was computed on both sides of the jump.  So make sure it isn't
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
-  TREE_INVARIANT (t) = 1;
   return t;
 }
 
@@ -2144,9 +2211,11 @@ skip_simple_arithmetic (tree expr)
 	inner = TREE_OPERAND (inner, 0);
       else if (BINARY_CLASS_P (inner))
 	{
-	  if (TREE_INVARIANT (TREE_OPERAND (inner, 1)))
+	  if (TREE_CONSTANT (TREE_OPERAND (inner, 1))
+	      || TREE_CODE (TREE_OPERAND (inner, 1)) == SAVE_EXPR)
 	    inner = TREE_OPERAND (inner, 0);
-	  else if (TREE_INVARIANT (TREE_OPERAND (inner, 0)))
+	  else if (TREE_CONSTANT (TREE_OPERAND (inner, 0))
+	           || TREE_CODE (TREE_OPERAND (inner, 0)) == SAVE_EXPR)
 	    inner = TREE_OPERAND (inner, 1);
 	  else
 	    break;
@@ -2815,7 +2884,7 @@ stabilize_reference_1 (tree e)
      ignore things that are actual constant or that already have been
      handled by this function.  */
 
-  if (TREE_INVARIANT (e))
+  if (TREE_CONSTANT (e))
     return e;
 
   switch (TREE_CODE_CLASS (code))
@@ -2868,7 +2937,6 @@ stabilize_reference_1 (tree e)
   TREE_READONLY (result) = TREE_READONLY (e);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
-  TREE_INVARIANT (result) = 1;
 
   return result;
 }
@@ -2876,13 +2944,13 @@ stabilize_reference_1 (tree e)
 /* Low-level constructors for expressions.  */
 
 /* A helper function for build1 and constant folders.  Set TREE_CONSTANT,
-   TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
+   and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
 
 void
 recompute_tree_invariant_for_addr_expr (tree t)
 {
   tree node;
-  bool tc = true, ti = true, se = false;
+  bool tc = true, se = false;
 
   /* We started out assuming this address is both invariant and constant, but
      does not have side effects.  Now go down any handled components and see if
@@ -2892,9 +2960,8 @@ recompute_tree_invariant_for_addr_expr (
      ??? Note that this code makes no attempt to deal with the case where
      taking the address of something causes a copy due to misalignment.  */
 
-#define UPDATE_TITCSE(NODE)  \
+#define UPDATE_FLAGS(NODE)  \
 do { tree _node = (NODE); \
-     if (_node && !TREE_INVARIANT (_node)) ti = false; \
      if (_node && !TREE_CONSTANT (_node)) tc = false; \
      if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
 
@@ -2908,11 +2975,11 @@ do { tree _node = (NODE); \
 	   || TREE_CODE (node) == ARRAY_RANGE_REF)
 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
 	{
-	  UPDATE_TITCSE (TREE_OPERAND (node, 1));
+	  UPDATE_FLAGS (TREE_OPERAND (node, 1));
 	  if (TREE_OPERAND (node, 2))
-	    UPDATE_TITCSE (TREE_OPERAND (node, 2));
+	    UPDATE_FLAGS (TREE_OPERAND (node, 2));
 	  if (TREE_OPERAND (node, 3))
-	    UPDATE_TITCSE (TREE_OPERAND (node, 3));
+	    UPDATE_FLAGS (TREE_OPERAND (node, 3));
 	}
       /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
 	 FIELD_DECL, apparently.  The G++ front end can put something else
@@ -2921,46 +2988,35 @@ do { tree _node = (NODE); \
 	       && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
 	{
 	  if (TREE_OPERAND (node, 2))
-	    UPDATE_TITCSE (TREE_OPERAND (node, 2));
+	    UPDATE_FLAGS (TREE_OPERAND (node, 2));
 	}
       else if (TREE_CODE (node) == BIT_FIELD_REF)
-	UPDATE_TITCSE (TREE_OPERAND (node, 2));
+	UPDATE_FLAGS (TREE_OPERAND (node, 2));
     }
 
-  node = lang_hooks.expr_to_decl (node, &tc, &ti, &se);
+  node = lang_hooks.expr_to_decl (node, &tc, &se);
 
   /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
-     the address, since &(*a)->b is a form of addition.  If it's a decl, it's
-     invariant and constant if the decl is static.  It's also invariant if it's
-     a decl in the current function.  Taking the address of a volatile variable
-     is not volatile.  If it's a constant, the address is both invariant and
-     constant.  Otherwise it's neither.  */
+     the address, since &(*a)->b is a form of addition.  If it's a constant, the
+     address is constant too.  If it's a decl, its address is constant if the
+     decl is static.  Everything else is not constant and, furthermore,
+     taking the address of a volatile variable is not volatile.  */
   if (TREE_CODE (node) == INDIRECT_REF)
-    UPDATE_TITCSE (TREE_OPERAND (node, 0));
-  else if (DECL_P (node))
-    {
-      if (staticp (node))
-	;
-      else if (decl_function_context (node) == current_function_decl
-	       /* Addresses of thread-local variables are invariant.  */
-	       || (TREE_CODE (node) == VAR_DECL
-		   && DECL_THREAD_LOCAL_P (node)))
-	tc = false;
-      else
-	ti = tc = false;
-    }
+    UPDATE_FLAGS (TREE_OPERAND (node, 0));
   else if (CONSTANT_CLASS_P (node))
     ;
+  else if (DECL_P (node))
+    tc &= (staticp (node) != NULL_TREE);
   else
     {
-      ti = tc = false;
+      tc = false;
       se |= TREE_SIDE_EFFECTS (node);
     }
 
+
   TREE_CONSTANT (t) = tc;
-  TREE_INVARIANT (t) = ti;
   TREE_SIDE_EFFECTS (t) = se;
-#undef UPDATE_TITCSE
+#undef UPDATE_FLAGS
 }
 
 /* Build an expression of code CODE, data type TYPE, and operands as
@@ -3057,9 +3113,6 @@ build1_stat (enum tree_code code, tree t
 	  && node && !TYPE_P (node)
 	  && TREE_CONSTANT (node))
 	TREE_CONSTANT (t) = 1;
-      if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR)
-	  && node && TREE_INVARIANT (node))
-	TREE_INVARIANT (t) = 1;
       if (TREE_CODE_CLASS (code) == tcc_reference
 	  && node && TREE_THIS_VOLATILE (node))
 	TREE_THIS_VOLATILE (t) = 1;
@@ -3080,15 +3133,13 @@ build1_stat (enum tree_code code, tree t
 	  read_only = 0;		\
         if (!TREE_CONSTANT (arg##N))	\
 	  constant = 0;			\
-	if (!TREE_INVARIANT (arg##N))	\
-	  invariant = 0;		\
       }					\
   } while (0)
 
 tree
 build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 2);
@@ -3125,14 +3176,12 @@ build2_stat (enum tree_code code, tree t
 	      || TREE_CODE_CLASS (code) == tcc_binary);
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
-  invariant = constant;
 
   PROCESS_ARG(0);
   PROCESS_ARG(1);
 
   TREE_READONLY (t) = read_only;
   TREE_CONSTANT (t) = constant;
-  TREE_INVARIANT (t) = invariant;
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
     = (TREE_CODE_CLASS (code) == tcc_reference
@@ -3161,7 +3210,7 @@ tree
 build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 	     tree arg2 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 3);
@@ -3197,7 +3246,7 @@ tree
 build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 	     tree arg2, tree arg3 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 4);
@@ -3224,7 +3273,7 @@ tree
 build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 	     tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 5);
@@ -3253,7 +3302,7 @@ build7_stat (enum tree_code code, tree t
 	     tree arg2, tree arg3, tree arg4, tree arg5,
 	     tree arg6 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (code == TARGET_MEM_REF);
@@ -3883,8 +3932,7 @@ merge_dllimport_decl_attributes (tree ol
 		   "after being referenced with dll linkage", new);
 	  /* If we have used a variable's address with dllimport linkage,
 	      keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
-	      decl may already have had TREE_INVARIANT and TREE_CONSTANT
-	      computed.
+	      decl may already have had TREE_CONSTANT computed.
 	      We still remove the attribute so that assembler code refers
 	      to '&foo rather than '_imp__foo'.  */
 	  if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
Index: tree.h
===================================================================
--- tree.h	(revision 133899)
+++ tree.h	(working copy)
@@ -387,7 +387,6 @@ struct tree_base GTY(())
   unsigned private_flag : 1;
   unsigned protected_flag : 1;
   unsigned deprecated_flag : 1;
-  unsigned invariant_flag : 1;
   unsigned saturating_flag : 1;
 
   unsigned lang_flag_0 : 1;
@@ -399,7 +398,7 @@ struct tree_base GTY(())
   unsigned lang_flag_6 : 1;
   unsigned visited : 1;
 
-  unsigned spare : 23;
+  unsigned spare : 24;
 
   /* FIXME tuples: Eventually, we need to move this somewhere external to
      the trees.  */
@@ -578,11 +577,6 @@ struct gimple_stmt GTY(())
 
    	Used in tree traversals to mark visited nodes.
 
-   invariant_flag:
-
-	TREE_INVARIANT in
-	    all expressions.
-
    saturating_flag:
 
        TYPE_SATURATING in
@@ -1371,12 +1365,6 @@ extern void omp_clause_range_check_faile
 #define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
   (IDENTIFIER_NODE_CHECK (NODE)->base.deprecated_flag)
 
-/* Value of expression is function invariant.  A strict subset of
-   TREE_CONSTANT, such an expression is constant over any one function
-   invocation, though not across different invocations.  May appear in
-   any expression node.  */
-#define TREE_INVARIANT(NODE) ((NODE)->base.invariant_flag)
-
 /* In fixed-point types, means a saturating type.  */
 #define TYPE_SATURATING(NODE) ((NODE)->base.saturating_flag)
 
@@ -4887,6 +4875,7 @@ extern tree strip_float_extensions (tree
 
 /* In tree.c */
 extern int really_constant_p (const_tree);
+extern bool invariant_addr_p (const_tree);
 extern int int_fits_type_p (const_tree, const_tree);
 #ifndef GENERATOR_FILE
 extern void get_type_static_bounds (const_tree, mpz_t, mpz_t);
Index: builtins.c
===================================================================
--- builtins.c	(revision 133899)
+++ builtins.c	(working copy)
@@ -5236,7 +5236,6 @@ build_string_literal (int len, const cha
   type = build_array_type (elem, index);
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = 1;
-  TREE_INVARIANT (t) = 1;
   TREE_READONLY (t) = 1;
   TREE_STATIC (t) = 1;
 
@@ -7150,7 +7149,7 @@ fold_builtin_expect (tree arg0, tree arg
     }
 
   /* If the argument isn't invariant then there's nothing else we can do.  */
-  if (!TREE_INVARIANT (arg0))
+  if (!TREE_CONSTANT (arg0))
     return NULL_TREE;
 
   /* If we expect that a comparison against the argument will fold to
Index: tree-gimple.c
===================================================================
--- tree-gimple.c	(revision 133899)
+++ tree-gimple.c	(working copy)
@@ -57,12 +57,14 @@ is_gimple_formal_tmp_rhs (tree t)
 
   switch (code)
     {
+    case ADDR_EXPR:
+      return is_gimple_address (t);
+
     case TRUTH_NOT_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
     case COND_EXPR:
-    case ADDR_EXPR:
     case CALL_EXPR:
     case CONSTRUCTOR:
     case COMPLEX_EXPR:
@@ -197,7 +199,7 @@ is_gimple_constant (const_tree t)
 /* Return true if T is a gimple invariant address.  */
 
 bool
-is_gimple_invariant_address (const_tree t)
+is_gimple_address (const_tree t)
 {
   tree op;
 
@@ -206,61 +208,24 @@ is_gimple_invariant_address (const_tree 
 
   op = TREE_OPERAND (t, 0);
   while (handled_component_p (op))
-    {
-      switch (TREE_CODE (op))
-	{
-	case ARRAY_REF:
-	case ARRAY_RANGE_REF:
-	  if (!is_gimple_constant (TREE_OPERAND (op, 1))
-	      || TREE_OPERAND (op, 2) != NULL_TREE
-	      || TREE_OPERAND (op, 3) != NULL_TREE)
-	    return false;
-	  break;
-
-	case COMPONENT_REF:
-	  if (TREE_OPERAND (op, 2) != NULL_TREE)
-	    return false;
-	  break;
-
-	default:;
-	}
-      op = TREE_OPERAND (op, 0);
-    }
+    op = TREE_OPERAND (op, 0);
 
-  if (CONSTANT_CLASS_P (op))
+  if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
     return true;
 
-  if (INDIRECT_REF_P (op))
-    return false;
-
   switch (TREE_CODE (op))
     {
     case PARM_DECL:
     case RESULT_DECL:
     case LABEL_DECL:
     case FUNCTION_DECL:
-      return true;
-
     case VAR_DECL:
-      if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
-	   && ! DECL_DLLIMPORT_P (op))
-	  || DECL_THREAD_LOCAL_P (op)
-	  || DECL_CONTEXT (op) == current_function_decl
-	  || decl_function_context (op) == current_function_decl)
-	return true;
-      break;
-
     case CONST_DECL:
-      if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
-	  || decl_function_context (op) == current_function_decl)
-	return true;
-      break;
+      return true;
 
     default:
-      gcc_unreachable ();
+      return false;
     }
-
-  return false;
 }
 
 /* Return true if T is a GIMPLE minimal invariant.  It's a restricted
@@ -270,7 +235,7 @@ bool
 is_gimple_min_invariant (const_tree t)
 {
   if (TREE_CODE (t) == ADDR_EXPR)
-    return is_gimple_invariant_address (t);
+    return invariant_addr_p (t);
 
   return is_gimple_constant (t);
 }
Index: tree-gimple.h
===================================================================
--- tree-gimple.h	(revision 133899)
+++ tree-gimple.h	(working copy)
@@ -62,8 +62,8 @@ extern bool is_gimple_addressable (tree)
 /* Returns true iff T is any valid GIMPLE lvalue.  */
 extern bool is_gimple_lvalue (tree);
 
-/* Returns true iff T is a GIMPLE invariant address.  */
-bool is_gimple_invariant_address (const_tree);
+/* Returns true iff T is a valid GIMPLE address.  */
+bool is_gimple_address (const_tree);
 /* Returns true iff T is a valid GIMPLE constant.  */
 bool is_gimple_constant (const_tree);
 /* Returns true iff T is a GIMPLE restricted function invariant.  */
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 133899)
+++ tree-ssa-ccp.c	(working copy)
@@ -2097,8 +2097,8 @@ fold_stmt_r (tree *expr_p, int *walk_sub
 	return t;
       *walk_subtrees = 0;
 
-      /* Set TREE_INVARIANT properly so that the value is properly
-	 considered constant, and so gets propagated as expected.  */
+      /* Make sure the value is properly considered constant, and so gets
+	 propagated as expected.  */
       if (*changed_p)
         recompute_tree_invariant_for_addr_expr (expr);
       return NULL_TREE;
Index: c-tree.h
===================================================================
--- c-tree.h	(revision 133899)
+++ c-tree.h	(working copy)
@@ -593,7 +593,7 @@ extern tree c_finish_goto_label (tree);
 extern tree c_finish_goto_ptr (tree);
 extern void c_begin_vm_scope (unsigned int);
 extern void c_end_vm_scope (unsigned int);
-extern tree c_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree c_expr_to_decl (tree, bool *, bool *);
 extern tree c_begin_omp_parallel (void);
 extern tree c_finish_omp_parallel (tree, tree);
 extern tree c_finish_omp_clauses (tree);
Index: langhooks.c
===================================================================
--- langhooks.c	(revision 133899)
+++ langhooks.c	(working copy)
@@ -502,8 +502,7 @@ lhd_to_target_charset (HOST_WIDE_INT c)
 }
 
 tree
-lhd_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
-		  bool *ti ATTRIBUTE_UNUSED, bool *se ATTRIBUTE_UNUSED)
+lhd_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se ATTRIBUTE_UNUSED)
 {
   return expr;
 }
Index: langhooks.h
===================================================================
--- langhooks.h	(revision 133900)
+++ langhooks.h	(working copy)
@@ -400,10 +400,9 @@ struct lang_hooks
   void (*init_ts) (void);
 
   /* Called by recompute_tree_invariant_for_addr_expr to go from EXPR
-     to a contained expression or DECL, possibly updating *TC, *TI or
-     *SE if in the process TREE_CONSTANT, TREE_INVARIANT or
-     TREE_SIDE_EFFECTS need updating.  */
-  tree (*expr_to_decl) (tree expr, bool *tc, bool *ti, bool *se);
+     to a contained expression or DECL, possibly updating *TC or *SE
+     if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
+  tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
 
   /* Whenever you add entries here, make sure you adjust langhooks-def.h
      and langhooks.c accordingly.  */
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 133899)
+++ c-typeck.c	(working copy)
@@ -2213,7 +2213,6 @@ build_external_ref (tree id, int fun, lo
       used_types_insert (TREE_TYPE (ref));
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
-      TREE_INVARIANT (ref) = 1;
     }
   else if (current_function_decl != 0
 	   && !DECL_FILE_SCOPE_P (current_function_decl)
@@ -3643,7 +3642,6 @@ build_c_cast (tree type, tree expr)
 			   build_constructor_single (type, field, value),
 			   true, 0);
 	  TREE_CONSTANT (t) = TREE_CONSTANT (value);
-	  TREE_INVARIANT (t) = TREE_INVARIANT (value);
 	  return t;
 	}
       error ("cast to union type from type not present in union");
@@ -5608,7 +5606,7 @@ pop_init_level (int implicit)
 	  ret.value = build_constructor (constructor_type,
 					 constructor_elements);
 	  if (constructor_constant)
-	    TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
+	    TREE_CONSTANT (ret.value) = 1;
 	  if (constructor_constant && constructor_simple)
 	    TREE_STATIC (ret.value) = 1;
 	}
@@ -8655,8 +8653,7 @@ c_objc_common_truthvalue_conversion (tre
    required.  */
 
 tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
-		bool *ti ATTRIBUTE_UNUSED, bool *se)
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
 {
   if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
     {
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 133899)
+++ gimplify.c	(working copy)
@@ -2868,12 +2868,14 @@ gimplify_init_ctor_preeval (tree *expr_p
 {
   enum gimplify_status one;
 
-  /* If the value is invariant, then there's nothing to pre-evaluate.
-     But ensure it doesn't have any side-effects since a SAVE_EXPR is
-     invariant but has side effects and might contain a reference to
-     the object we're initializing.  */
-  if (TREE_INVARIANT (*expr_p) && !TREE_SIDE_EFFECTS (*expr_p))
-    return;
+  /* If the value is constant, then there's nothing to pre-evaluate.  */
+  if (TREE_CONSTANT (*expr_p))
+    {
+      /* Ensure it does not have side effects, it might contain a reference to
+	 the object we're initializing.  */
+      gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
+      return;
+    }
 
   /* If the type has non-trivial constructors, we can't pre-evaluate.  */
   if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
@@ -3416,7 +3418,6 @@ gimplify_init_constructor (tree *expr_p,
 	      break;
 
 	    TREE_CONSTANT (ctor) = 0;
-	    TREE_INVARIANT (ctor) = 0;
 	  }
 
 	/* Vector types use CONSTRUCTOR all the way through gimple
@@ -4254,8 +4255,7 @@ gimplify_addr_expr (tree *expr_p, tree *
 	  if (TREE_CODE (op0) == INDIRECT_REF)
 	    goto do_indirect_ref;
 
-	  /* Make sure TREE_INVARIANT, TREE_CONSTANT, and TREE_SIDE_EFFECTS
-	     is set properly.  */
+	  /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly.  */
 	  recompute_tree_invariant_for_addr_expr (expr);
 
 	  mark_addressable (TREE_OPERAND (expr, 0));
Index: tree-mudflap.c
===================================================================
--- tree-mudflap.c	(revision 133899)
+++ tree-mudflap.c	(working copy)
@@ -83,7 +83,6 @@ mf_build_string (const char *string)
   TREE_TYPE (result) = build_array_type
     (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
   TREE_CONSTANT (result) = 1;
-  TREE_INVARIANT (result) = 1;
   TREE_READONLY (result) = 1;
   TREE_STATIC (result) = 1;
 
Index: print-tree.c
===================================================================
--- print-tree.c	(revision 133899)
+++ print-tree.c	(working copy)
@@ -292,8 +292,6 @@ print_node (FILE *file, const char *pref
   else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
     fputs (" sizes-gimplified", file);
 
-  if (TREE_INVARIANT (node))
-    fputs (" invariant", file);
   if (TREE_ADDRESSABLE (node))
     fputs (" addressable", file);
   if (TREE_THIS_VOLATILE (node))
Index: tree-nested.c
===================================================================
--- tree-nested.c	(revision 133899)
+++ tree-nested.c	(working copy)
@@ -1037,8 +1037,8 @@ convert_nonlocal_reference (tree *tp, in
 	  {
 	    tree save_context;
 
-	    /* If we changed anything, then TREE_INVARIANT is be wrong,
-	       since we're no longer directly referencing a decl.  */
+	    /* If we changed anything, we might no longer be directly
+	       referencing a decl.  */
 	    save_context = current_function_decl;
 	    current_function_decl = info->context;
 	    recompute_tree_invariant_for_addr_expr (t);
Index: c-common.c
===================================================================
--- c-common.c	(revision 133899)
+++ c-common.c	(working copy)
@@ -907,7 +907,6 @@ fix_string_type (tree value)
 
   TREE_TYPE (value) = a_type;
   TREE_CONSTANT (value) = 1;
-  TREE_INVARIANT (value) = 1;
   TREE_READONLY (value) = 1;
   TREE_STATIC (value) = 1;
   return value;
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 133900)
+++ tree-cfg.c	(working copy)
@@ -3161,28 +3161,20 @@ verify_expr (tree *tp, int *walk_subtree
 
     case ADDR_EXPR:
       {
-	bool old_invariant;
 	bool old_constant;
 	bool old_side_effects;
-	bool new_invariant;
 	bool new_constant;
 	bool new_side_effects;
 
-	old_invariant = TREE_INVARIANT (t);
+	gcc_assert (is_gimple_address (t));
+
 	old_constant = TREE_CONSTANT (t);
 	old_side_effects = TREE_SIDE_EFFECTS (t);
 
 	recompute_tree_invariant_for_addr_expr (t);
-	new_invariant = TREE_INVARIANT (t);
 	new_side_effects = TREE_SIDE_EFFECTS (t);
 	new_constant = TREE_CONSTANT (t);
 
-	if (old_invariant != new_invariant)
-	  {
-	    error ("invariant not recomputed when ADDR_EXPR changed");
-	    return t;
-	  }
-
         if (old_constant != new_constant)
 	  {
 	    error ("constant not recomputed when ADDR_EXPR changed");
Index: langhooks-def.h
===================================================================
--- langhooks-def.h	(revision 133900)
+++ langhooks-def.h	(working copy)
@@ -64,7 +64,7 @@ extern const char *lhd_comdat_group (tre
 extern tree lhd_expr_size (const_tree);
 extern size_t lhd_tree_size (enum tree_code);
 extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
-extern tree lhd_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree lhd_expr_to_decl (tree, bool *, bool *);
 extern tree lhd_builtin_function (tree decl);
 
 /* Declarations of default tree inlining hooks.  */
Index: java/class.c
===================================================================
--- java/class.c	(revision 133899)
+++ java/class.c	(working copy)
@@ -955,7 +955,6 @@ build_utf8_ref (tree name)
   PUSH_FIELD_VALUE (cinit, "data", string);
   FINISH_RECORD_CONSTRUCTOR (cinit);
   TREE_CONSTANT (cinit) = 1;
-  TREE_INVARIANT (cinit) = 1;
 
   /* Generate a unique-enough identifier.  */
   sprintf(buf, "_Utf%d", ++utf8_count);
@@ -1063,7 +1062,6 @@ build_classdollar_field (tree type)
 					     /* const */ 1, 0)),
 			/* const */ 1, 0)));
       TREE_STATIC (decl) = 1;
-      TREE_INVARIANT (decl) = 1;
       TREE_CONSTANT (decl) = 1;
       TREE_READONLY (decl) = 1;
       TREE_PUBLIC (decl) = 1;
@@ -1604,7 +1602,6 @@ get_dispatch_table (tree type, tree this
 		tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node, 
 				     method, build_int_cst (NULL_TREE, j));
 		TREE_CONSTANT (fdesc) = 1;
-		TREE_INVARIANT (fdesc) = 1;
 	        list = tree_cons (NULL_TREE, fdesc, list);
 	      }
 	  else
@@ -2076,7 +2073,6 @@ make_class_data (tree type)
 			build1 (ADDR_EXPR, symbols_array_ptr_type,
 				TYPE_OTABLE_SYMS_DECL (type)));
       TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_OTABLE_DECL (type)) = 1;
     }
   if (TYPE_ATABLE_METHODS(type) == NULL_TREE)
     {
@@ -2092,7 +2088,6 @@ make_class_data (tree type)
 			build1 (ADDR_EXPR, symbols_array_ptr_type,
 				TYPE_ATABLE_SYMS_DECL (type)));
       TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1;
     }
    if (TYPE_ITABLE_METHODS(type) == NULL_TREE)
     {
@@ -2108,7 +2103,6 @@ make_class_data (tree type)
 			build1 (ADDR_EXPR, symbols_array_ptr_type,
 				TYPE_ITABLE_SYMS_DECL (type)));
       TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_ITABLE_DECL (type)) = 1;
     }
  
   PUSH_FIELD_VALUE (cons, "catch_classes",
@@ -2848,7 +2842,6 @@ build_symbol_entry (tree decl, tree spec
   PUSH_FIELD_VALUE (sym, "signature", signature);
   FINISH_RECORD_CONSTRUCTOR (sym);
   TREE_CONSTANT (sym) = 1;
-  TREE_INVARIANT (sym) = 1;
 
   return sym;
 } 
@@ -2889,7 +2882,6 @@ emit_symbol_table (tree name, tree the_t
   PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
   FINISH_RECORD_CONSTRUCTOR (null_symbol);
   TREE_CONSTANT (null_symbol) = 1;  
-  TREE_INVARIANT (null_symbol) = 1;  
   list = tree_cons (NULL_TREE, null_symbol, list);
 
   /* Put the list in the right order and make it a constructor. */
Index: java/constants.c
===================================================================
--- java/constants.c	(revision 133899)
+++ java/constants.c	(working copy)
@@ -445,7 +445,6 @@ build_constant_data_ref (bool indirect)
       TREE_THIS_NOTRAP (klass) = 1;
       data = fold_convert (build_pointer_type (cpool_type), data);
       d = build1 (INDIRECT_REF, cpool_type, data);
-      TREE_INVARIANT (d) = 1;
 
       return d;
     }
@@ -485,7 +484,6 @@ build_ref_from_constant_pool (int index)
   i = build_int_cst (NULL_TREE, index);
   d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
 		 NULL_TREE, NULL_TREE);
-  TREE_INVARIANT (d) = 1;
   return d;
 }
 
Index: java/resource.c
===================================================================
--- java/resource.c	(revision 133899)
+++ java/resource.c	(working copy)
@@ -73,7 +73,6 @@ compile_resource_data (const char *name,
   PUSH_FIELD_VALUE (rinit, "data", data);
   FINISH_RECORD_CONSTRUCTOR (rinit);
   TREE_CONSTANT (rinit) = 1;
-  TREE_INVARIANT (rinit) = 1;
 
   decl = build_decl (VAR_DECL, java_mangle_resource_name (name), rtype);
   TREE_STATIC (decl) = 1;
Index: java/expr.c
===================================================================
--- java/expr.c	(revision 133899)
+++ java/expr.c	(working copy)
@@ -3809,7 +3809,6 @@ cache_cpool_data_ref (void)
       tree cpool_ptr = build_decl (VAR_DECL, NULL_TREE, 
 				   build_pointer_type (TREE_TYPE (d)));
       java_add_local_var (cpool_ptr);
-      TREE_INVARIANT (cpool_ptr) = 1;
       TREE_CONSTANT (cpool_ptr) = 1;
 
       java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (cpool_ptr), 
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 133899)
+++ objc/objc-act.c	(working copy)
@@ -1953,7 +1953,6 @@ objc_build_string_object (tree string)
  			    initlist);
       constructor = objc_build_constructor (internal_const_str_type,
 					    nreverse (initlist));
-      TREE_INVARIANT (constructor) = true;
 
       if (!flag_next_runtime)
 	constructor
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 133899)
+++ cp/typeck.c	(working copy)
@@ -2764,7 +2764,6 @@ get_member_function_from_ptrfunc (tree *
 			fold_convert (sizetype, idx));
       e2 = cp_build_indirect_ref (e2, NULL, tf_warning_or_error);
       TREE_CONSTANT (e2) = 1;
-      TREE_INVARIANT (e2) = 1;
 
       /* When using function descriptors, the address of the
 	 vtable entry is treated as a function pointer.  */
@@ -6394,7 +6393,6 @@ build_ptrmemfunc1 (tree type, tree delta
   CONSTRUCTOR_APPEND_ELT(v, delta_field, delta);
   u = build_constructor (type, v);
   TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
-  TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta);
   TREE_STATIC (u) = (TREE_CONSTANT (u)
 		     && (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
 			 != NULL_TREE)
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 133899)
+++ cp/init.c	(working copy)
@@ -261,10 +261,7 @@ build_zero_init (tree type, tree nelts, 
 
   /* In all cases, the initializer is a constant.  */
   if (init)
-    {
-      TREE_CONSTANT (init) = 1;
-      TREE_INVARIANT (init) = 1;
-    }
+    TREE_CONSTANT (init) = 1;
 
   return init;
 }
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 133899)
+++ cp/class.c	(working copy)
@@ -385,7 +385,6 @@ build_base_path (enum tree_code code,
 			 v_offset);
       v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error);
       TREE_CONSTANT (v_offset) = 1;
-      TREE_INVARIANT (v_offset) = 1;
 
       offset = convert_to_integer (ptrdiff_type_node,
 				   size_diffop (offset,
@@ -630,7 +629,6 @@ build_vtbl_ref_1 (tree instance, tree id
 
   aref = build_array_ref (vtbl, idx);
   TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
-  TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
 
   return aref;
 }
@@ -7448,7 +7446,6 @@ build_vtbl_initializer (tree binfo,
 				     TREE_OPERAND (init, 0),
 				     build_int_cst (NULL_TREE, i));
 		TREE_CONSTANT (fdesc) = 1;
-		TREE_INVARIANT (fdesc) = 1;
 
 		vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
 	      }
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 133900)
+++ cp/decl.c	(working copy)
@@ -10957,7 +10957,6 @@ build_enumerator (tree name, tree value,
 
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
   TREE_CONSTANT (decl) = 1;
-  TREE_INVARIANT (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_INITIAL (decl) = value;
 
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 133899)
+++ cp/rtti.c	(working copy)
@@ -902,7 +902,6 @@ tinfo_base_init (tinfo_s *ti, tree targe
 
   init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   init = tree_cons (NULL_TREE, init, NULL_TREE);
 
@@ -920,7 +919,6 @@ generic_initializer (tinfo_s *ti, tree t
 
   init = build_constructor_from_list (NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -946,7 +944,6 @@ ptr_initializer (tinfo_s *ti, tree targe
 
   init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -979,7 +976,6 @@ ptm_initializer (tinfo_s *ti, tree targe
 
   init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -996,7 +992,6 @@ class_initializer (tinfo_s *ti, tree tar
   TREE_CHAIN (init) = trail;
   init = build_constructor_from_list (NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 133899)
+++ cp/typeck2.c	(working copy)
@@ -1081,7 +1081,6 @@ process_init_constructor (tree type, tre
   if (!(flags & PICFLAG_NOT_ALL_CONSTANT))
     {
       TREE_CONSTANT (init) = 1;
-      TREE_INVARIANT (init) = 1;
       if (!(flags & PICFLAG_NOT_ALL_SIMPLE))
 	TREE_STATIC (init) = 1;
     }
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 133899)
+++ cp/pt.c	(working copy)
@@ -384,7 +384,6 @@ push_inline_template_parms_recursive (tr
 				    TREE_TYPE (parm));
 	    DECL_ARTIFICIAL (decl) = 1;
 	    TREE_CONSTANT (decl) = 1;
-	    TREE_INVARIANT (decl) = 1;
 	    TREE_READONLY (decl) = 1;
 	    DECL_INITIAL (decl) = DECL_INITIAL (parm);
 	    SET_DECL_TEMPLATE_PARM_P (decl);
@@ -2870,7 +2869,6 @@ build_template_parm_index (int index,
   TEMPLATE_PARM_DECL (t) = decl;
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = TREE_CONSTANT (decl);
-  TREE_INVARIANT (t) = TREE_INVARIANT (decl);
   TREE_READONLY (t) = TREE_READONLY (decl);
 
   return t;
@@ -2923,7 +2921,6 @@ reduce_template_parm_level (tree index, 
 
       decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
       TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
-      TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
       TREE_READONLY (decl) = TREE_READONLY (orig_decl);
       DECL_ARTIFICIAL (decl) = 1;
       SET_DECL_TEMPLATE_PARM_P (decl);
@@ -3020,11 +3017,9 @@ process_template_parm (tree list, tree p
 
       /* A template parameter is not modifiable.  */
       TREE_CONSTANT (parm) = 1;
-      TREE_INVARIANT (parm) = 1;
       TREE_READONLY (parm) = 1;
       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
       TREE_CONSTANT (decl) = 1;
-      TREE_INVARIANT (decl) = 1;
       TREE_READONLY (decl) = 1;
       DECL_INITIAL (parm) = DECL_INITIAL (decl)
 	= build_template_parm_index (idx, processing_template_decl,
Index: ada/trans.c
===================================================================
--- ada/trans.c	(revision 133899)
+++ ada/trans.c	(working copy)
@@ -1234,7 +1234,6 @@ Attribute_to_gnu (Node_Id gnat_node, tre
 	    gnu_result
 	      = build1 (SAVE_EXPR, TREE_TYPE (gnu_result), gnu_result);
 	    TREE_SIDE_EFFECTS (gnu_result) = 1;
-	    TREE_INVARIANT (gnu_result) = 1;
 	    if (attribute == Attr_First)
 	      pa->first = gnu_result;
 	    else if (attribute == Attr_Last)
@@ -2174,7 +2173,6 @@ call_to_gnu (Node_Id gnat_node, tree *gn
 	     used as the object and copied back after the call if needed.  */
 	  gnu_name = build1 (SAVE_EXPR, TREE_TYPE (gnu_name), gnu_name);
 	  TREE_SIDE_EFFECTS (gnu_name) = 1;
-	  TREE_INVARIANT (gnu_name) = 1;
 
 	  /* Set up to move the copy back to the original.  */
 	  if (Ekind (gnat_formal) != E_In_Parameter)
Index: ada/utils2.c
===================================================================
--- ada/utils2.c	(revision 133899)
+++ ada/utils2.c	(working copy)
@@ -1656,8 +1656,7 @@ gnat_build_constructor (tree type, tree 
     }
 
   result = build_constructor_from_list (type, list);
-  TREE_CONSTANT (result) = TREE_INVARIANT (result)
-    = TREE_STATIC (result) = allconstant;
+  TREE_CONSTANT (result) = TREE_STATIC (result) = allconstant;
   TREE_SIDE_EFFECTS (result) = side_effects;
   TREE_READONLY (result) = TYPE_READONLY (type) || allconstant;
   return result;
Index: fortran/trans-expr.c
===================================================================
--- fortran/trans-expr.c	(revision 133899)
+++ fortran/trans-expr.c	(working copy)
@@ -3478,10 +3478,7 @@ gfc_conv_structure (gfc_se * se, gfc_exp
     }
   se->expr = build_constructor (type, v);
   if (init) 
-    {
-      TREE_CONSTANT(se->expr) = 1;
-      TREE_INVARIANT(se->expr) = 1;
-    }
+    TREE_CONSTANT (se->expr) = 1;
 }
 
 
Index: fortran/trans-array.c
===================================================================
--- fortran/trans-array.c	(revision 133899)
+++ fortran/trans-array.c	(working copy)
@@ -316,7 +316,6 @@ gfc_build_null_descriptor (tree type)
   /* Set a NULL data pointer.  */
   tmp = build_constructor_single (type, field, null_pointer_node);
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   /* All other fields are ignored.  */
 
   return tmp;
@@ -1207,13 +1206,11 @@ gfc_trans_array_constructor_value (stmtb
 
 	      init = build_constructor_from_list (tmptype, nreverse (list));
 	      TREE_CONSTANT (init) = 1;
-	      TREE_INVARIANT (init) = 1;
 	      TREE_STATIC (init) = 1;
 	      /* Create a static variable to hold the data.  */
 	      tmp = gfc_create_var (tmptype, "data");
 	      TREE_STATIC (tmp) = 1;
 	      TREE_CONSTANT (tmp) = 1;
-	      TREE_INVARIANT (tmp) = 1;
 	      TREE_READONLY (tmp) = 1;
 	      DECL_INITIAL (tmp) = init;
 	      init = tmp;
@@ -1582,13 +1579,11 @@ gfc_build_constant_array_constructor (gf
   init = build_constructor_from_list (tmptype, nreverse (list));
 
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
 
   tmp = gfc_create_var (tmptype, "A");
   TREE_STATIC (tmp) = 1;
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   TREE_READONLY (tmp) = 1;
   DECL_INITIAL (tmp) = init;
 
@@ -3885,7 +3880,6 @@ gfc_conv_array_initializer (tree type, g
   /* Create a constructor from the list of elements.  */
   tmp = build_constructor (type, v);
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   return tmp;
 }
 
Index: fortran/trans-common.c
===================================================================
--- fortran/trans-common.c	(revision 133899)
+++ fortran/trans-common.c	(working copy)
@@ -547,7 +547,6 @@ get_init_field (segment_info *head, tree
 
   init = build_constructor (TREE_TYPE (field), v);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
 
   *field_init = init;
 
@@ -657,7 +656,6 @@ create_common (gfc_common_head *com, seg
       gcc_assert (!VEC_empty (constructor_elt, v));
       ctor = build_constructor (union_type, v);
       TREE_CONSTANT (ctor) = 1;
-      TREE_INVARIANT (ctor) = 1;
       TREE_STATIC (ctor) = 1;
       DECL_INITIAL (decl) = ctor;
 
Index: fortran/trans-stmt.c
===================================================================
--- fortran/trans-stmt.c	(revision 133899)
+++ fortran/trans-stmt.c	(working copy)
@@ -1435,12 +1435,10 @@ gfc_trans_character_select (gfc_code *co
 
   init = build_constructor_from_list (type, nreverse(init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   /* Create a static variable to hold the jump table.  */
   tmp = gfc_create_var (type, "jumptable");
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   TREE_STATIC (tmp) = 1;
   TREE_READONLY (tmp) = 1;
   DECL_INITIAL (tmp) = init;
Index: fortran/trans-decl.c
===================================================================
--- fortran/trans-decl.c	(revision 133899)
+++ fortran/trans-decl.c	(working copy)
@@ -3185,13 +3185,11 @@ gfc_generate_function_code (gfc_namespac
 								      6)));
       array = build_constructor_from_list (array_type, nreverse (array));
       TREE_CONSTANT (array) = 1;
-      TREE_INVARIANT (array) = 1;
       TREE_STATIC (array) = 1;
 
       /* Create a static variable to hold the jump table.  */
       var = gfc_create_var (array_type, "options");
       TREE_CONSTANT (var) = 1;
-      TREE_INVARIANT (var) = 1;
       TREE_STATIC (var) = 1;
       TREE_READONLY (var) = 1;
       DECL_INITIAL (var) = array;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05  7:36 [PATCH] Eliminate TREE_INVARIANT Paolo Bonzini
@ 2008-04-05  7:40 ` Eric Botcazou
  2008-04-05  7:58   ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Eric Botcazou @ 2008-04-05  7:40 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: gcc-patches

> There's one exception in save_expr, where we want to not wrap invariant
> addresses: for this I used is_gimple_invariant_address after modifying
> it to not crash for front-end specific trees (this is the new function
> invariant_addr_p in tree.c; functions in tree.c don't use is_* apparently).

save_expr and tree.c are supposed to deal with GENERIC trees, not GIMPLE ones, 
so is using is_gimple_constant in invariant_addr_p really appropriate?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05  7:40 ` Eric Botcazou
@ 2008-04-05  7:58   ` Paolo Bonzini
  2008-04-05 12:39     ` Richard Guenther
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-05  7:58 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> save_expr and tree.c are supposed to deal with GENERIC trees, not GIMPLE ones, 

Yes, that's why I introduced invariant_addr_p.

> so is using is_gimple_constant in invariant_addr_p really appropriate?

You're right in objecting to that.  The reason why I did it is that in 
this particular case (i.e. as operand 1 of an ARRAY_REF/ARRAY_RANGE_REF) 
you cannot expect (IMO) an arbitrary constant, but only for example an 
INTEGER_CST.  I didn't want to change the semantics of the GIMPLE part 
of the compiler (introducing more stringent checks was okay, but I aimed 
at no assembly output changes), so I used a check that is 
not-so-appropriate for this part of the compiler.

So, considering that is_gimple_constant passes only CONSTANT_CLASS_P 
nodes, plus constructors in this special case...

     case CONSTRUCTOR:
       if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
         return TREE_CONSTANT (t);
       else
         return false;

... then the possible alternatives to is_gimple_constant could be:
- CONSTANT_CLASS_P (t)
- TREE_CONSTANT (t)
- TREE_CONSTANT (t) || TREE_CODE (t) == SAVE_EXPR.

I can retest with any of these changes, or do it in a follow-up patch, 
depending on what a maintainer (or another contributor -- your opinion 
is as valuable) tells me.

Thanks for the remark,

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05  7:58   ` Paolo Bonzini
@ 2008-04-05 12:39     ` Richard Guenther
  2008-04-05 12:41       ` Paolo Bonzini
  2008-04-07 12:40       ` Paolo Bonzini
  0 siblings, 2 replies; 14+ messages in thread
From: Richard Guenther @ 2008-04-05 12:39 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Eric Botcazou, gcc-patches

On Sat, Apr 5, 2008 at 9:40 AM, Paolo Bonzini <bonzini@gnu.org> wrote:
>
>
> > save_expr and tree.c are supposed to deal with GENERIC trees, not GIMPLE
> ones,
> >
>
>  Yes, that's why I introduced invariant_addr_p.
>
>
>
> > so is using is_gimple_constant in invariant_addr_p really appropriate?
> >
>
>  You're right in objecting to that.  The reason why I did it is that in this
> particular case (i.e. as operand 1 of an ARRAY_REF/ARRAY_RANGE_REF) you
> cannot expect (IMO) an arbitrary constant, but only for example an
> INTEGER_CST.  I didn't want to change the semantics of the GIMPLE part of
> the compiler (introducing more stringent checks was okay, but I aimed at no
> assembly output changes), so I used a check that is not-so-appropriate for
> this part of the compiler.
>
>  So, considering that is_gimple_constant passes only CONSTANT_CLASS_P nodes,
> plus constructors in this special case...
>
>     case CONSTRUCTOR:
>       if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
>         return TREE_CONSTANT (t);
>       else
>         return false;
>
>  ... then the possible alternatives to is_gimple_constant could be:
>  - CONSTANT_CLASS_P (t)
>  - TREE_CONSTANT (t)
>  - TREE_CONSTANT (t) || TREE_CODE (t) == SAVE_EXPR.
>
>  I can retest with any of these changes, or do it in a follow-up patch,
> depending on what a maintainer (or another contributor -- your opinion is as
> valuable) tells me.

TREE_CONSTANT would be ok I think (if it works), but of course this leaks into
the gimple predicates then.  Maybe a safer approach is to bite the bullet and
duplicate the function, once for tree-gimple.c and once for tree.c?

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05 12:39     ` Richard Guenther
@ 2008-04-05 12:41       ` Paolo Bonzini
  2008-04-05 12:46         ` Richard Guenther
  2008-04-07 12:40       ` Paolo Bonzini
  1 sibling, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-05 12:41 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Eric Botcazou, gcc-patches


> TREE_CONSTANT would be ok I think (if it works), but of course this leaks into
> the gimple predicates then.  Maybe a safer approach is to bite the bullet and
> duplicate the function, once for tree-gimple.c and once for tree.c?

What about just

   TREE_CODE (t) == INTEGER_CST || TREE_CODE (t) == SAVE_EXPR

and adding a check in is_gimple_address so that SAVE_EXPR would be ruled 
out in the verifier?  Can you have other kinds of constant as an array 
index?

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05 12:41       ` Paolo Bonzini
@ 2008-04-05 12:46         ` Richard Guenther
  2008-04-05 14:35           ` Paolo Bonzini
  2008-04-09  1:00           ` Mark Mitchell
  0 siblings, 2 replies; 14+ messages in thread
From: Richard Guenther @ 2008-04-05 12:46 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Eric Botcazou, gcc-patches

On Sat, Apr 5, 2008 at 2:34 PM, Paolo Bonzini <bonzini@gnu.org> wrote:
>
>
> > TREE_CONSTANT would be ok I think (if it works), but of course this leaks
> into
> > the gimple predicates then.  Maybe a safer approach is to bite the bullet
> and
> > duplicate the function, once for tree-gimple.c and once for tree.c?
> >
>
>  What about just
>
>   TREE_CODE (t) == INTEGER_CST || TREE_CODE (t) == SAVE_EXPR
>
>  and adding a check in is_gimple_address so that SAVE_EXPR would be ruled
> out in the verifier?  Can you have other kinds of constant as an array
> index?

Not really, but maybe the FEs depend on things like

const int i = 5;
&a[i]

being an invariant address?  Of course after ccp (or even gimplification) that
will become &a[5], but you might want to check what happens here with -O0,
whether we create different code for the proposed variants of the check.

Why is SAVE_EXPR special here btw?  SAVE_EXPR should just "clear"
TREE_SIDE_EFFECTS, but not change invariantness or constness of its
argument, no?

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05 12:46         ` Richard Guenther
@ 2008-04-05 14:35           ` Paolo Bonzini
  2008-04-09  1:00           ` Mark Mitchell
  1 sibling, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-05 14:35 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Eric Botcazou, gcc-patches


> Not really, but maybe the FEs depend on things like
> 
> const int i = 5;
> &a[i]
> 
> being an invariant address?  Of course after ccp (or even gimplification) that
> will become &a[5], but you might want to check what happens here with -O0,
> whether we create different code for the proposed variants of the check.

Ok.

> Why is SAVE_EXPR special here btw?  SAVE_EXPR should just "clear"
> TREE_SIDE_EFFECTS, but not change invariantness or constness of its
> argument, no?

The point of SAVE_EXPR is to make something invariant even though it has 
side effects.  From the GENERIC point of view, SAVE_EXPR must be treated 
as invariant.

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05 12:39     ` Richard Guenther
  2008-04-05 12:41       ` Paolo Bonzini
@ 2008-04-07 12:40       ` Paolo Bonzini
  1 sibling, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-07 12:40 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Eric Botcazou, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 712 bytes --]

Richard Guenther wrote:
> On Sat, Apr 5, 2008 at 9:40 AM, Paolo Bonzini <bonzini@gnu.org> wrote:
>>
>>> save_expr and tree.c are supposed to deal with GENERIC trees, not GIMPLE
>>> ones, so is using is_gimple_constant in invariant_addr_p really appropriate?
>
> TREE_CONSTANT would be ok I think (if it works

Unfortunately it didn't.  It was too broad, as it included for example 
NOP_EXPRs of a constant, and this upsets the testcases for PR34029 and 
PR35607.

However, the patch I had already posted, with TREE_CODE (t) == 
INTEGER_CST instead of is_gimple_constant (t) in invariant_addr_p, 
regstrapped ok on i686-pc-linux-gnu, all languages including Ada.  The 
patch is attached.

Ok for mainline?

Paolo

[-- Attachment #2: kill-tree-invariant.patch --]
[-- Type: text/plain, Size: 46593 bytes --]

2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* tree-gimple.c (is_gimple_address): New from...
	(is_gimple_invariant_address): ... this one.
	(is_gimple_formal_tmp_rhs): Use it.
	* tree-gimple.h (is_gimple_address): New prototype replacing...
	(is_gimple_invariant_address): ... this one.
	* tree-cfg.c (verify_expr): Don't verify TREE_INVARIANT.
	Use is_gimple_address.
	* tree.c (make_node_stat): Don't set TREE_INVARIANT.
	(build_string): Likewise.
	(invariant_addr_p): New, from is_gimple_invariant_address.
	(save_expr): Use invariant_addr_p or TREE_CONSTANT.
	(skip_simple_arithmetic): Likewise, also check for SAVE_EXPRs.
	(stabilize_reference_1): Check TREE_CONSTANT, other invariant
	things are already wrapped into SAVE_EXPR.
	(recompute_tree_invariant_for_addr_expr): Don't update TREE_INVARIANT,
	simplify.
	(build1_stat): Drop code to compute TREE_INVARIANT.
	(build2_stat): Drop code to compute TREE_INVARIANT.
	(build3_stat): Drop code to compute TREE_INVARIANT.
	(build4_stat): Drop code to compute TREE_INVARIANT.
	(build5_stat): Drop code to compute TREE_INVARIANT.
	(build7_stat): Drop code to compute TREE_INVARIANT.
	(merge_dllimport_decl_attributes): Don't mention TREE_INVARIANT.
	* tree.h (struct tree_base): Remove invariant_flag.
	(TREE_INVARIANT): Remove.
	* builtins.c (build_string_literal): Don't set TREE_INVARIANT.
	(fold_builtin_expect): Check TREE_CONSTANT.
	* tree-ssa-ccp.c (fold_stmt_r): Adjust comment.
	* c-tree.h (c_expr_to_decl): Drop third parameter.
	* c-typeck.c (build_external_ref): Don't set TREE_INVARIANT.
	(build_c_cast): Don't set TREE_INVARIANT.
	(pop_init_level): Don't set TREE_INVARIANT.
	(c_objc_common_truthvalue_conversion): Don't set TREE_INVARIANT.
	* gimplify.c (gimplify_init_ctor_preeval): Add assertion, test
	TREE_CONSTANT.
	(gimplify_init_constructor): Don't set TREE_INVARIANT.
	(gimplify_addr_expr): Adjust comment.
	* tree-mudflap.c (mf_build_string):
	* print-tree.c (print_node): Don't print TREE_INVARIANT.
	* tree-nested.c (convert_nonlocal_reference): Adjust comment.
	* c-common.c (fix_string_type): Don't set TREE_INVARIANT.
	* langhooks-def.h (lhd_expr_to_decl): Drop third parameter.
	* langhooks.c (lhd_expr_to_decl): Drop third parameter.
	* langhooks.h (struct lang_hooks): Drop third parameter from
	expr_to_decl.

java:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* class.c (build_utf8_ref): Don't set TREE_INVARIANT.
	(build_classdollar_field): Don't set TREE_INVARIANT.
	(get_dispatch_table): Don't set TREE_INVARIANT.
	(make_class_data): Don't set TREE_INVARIANT.
	(build_symbol_entry): Don't set TREE_INVARIANT.
	(emit_symbol_table): Don't set TREE_INVARIANT.
	* constants.c (build_constant_data_ref): Don't set TREE_INVARIANT.
	(build_ref_from_constant_pool): Don't set TREE_INVARIANT.
	* resource.c (compile_resource_data): Don't set TREE_INVARIANT.
	* expr.c (cache_cpool_data_ref): Don't set TREE_INVARIANT.

objc:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* objc-act.c (objc_build_string_object): Don't set TREE_INVARIANT.

cp:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* typeck.c (get_member_function_from_ptrfunc): Don't set TREE_INVARIANT.
	(build_ptrmemfunc1): Don't set TREE_INVARIANT.
	* init.c (build_zero_init): Don't set TREE_INVARIANT.
	* class.c (build_base_path): Don't set TREE_INVARIANT.
	(build_vtbl_ref_1): Don't set TREE_INVARIANT.
	(build_vtbl_initializer): Don't set TREE_INVARIANT.
	* decl.c (build_enumerator): Don't set TREE_INVARIANT.
	* rtti.c (tinfo_base_init): Don't set TREE_INVARIANT.
	(generic_initializer): Don't set TREE_INVARIANT.
	(ptr_initializer): Don't set TREE_INVARIANT.
	(ptm_initializer): Don't set TREE_INVARIANT.
	(class_initializer): Don't set TREE_INVARIANT.
	* typeck2.c (process_init_constructor): Don't set TREE_INVARIANT.
	* pt.c (push_inline_template_parms_recursive): Don't set TREE_INVARIANT.
	(build_template_parm_index): Don't set TREE_INVARIANT.
	(reduce_template_parm_level): Don't set TREE_INVARIANT.
	(process_template_parm): Don't set TREE_INVARIANT.

ada:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* trans.c (Attribute_to_gnu): Don't set TREE_INVARIANT.
	(call_to_gnu): Don't set TREE_INVARIANT.
	* utils2.c (gnat_build_constructor): Don't set TREE_INVARIANT.

fortran:
2008-04-04  Paolo Bonzini  <bonzini@gnu.org>

	* trans-expr.c (gfc_conv_structure): Don't set TREE_INVARIANT.
	* trans-array.c (gfc_build_null_descriptor): Don't set TREE_INVARIANT.
	(gfc_trans_array_constructor_value): Don't set TREE_INVARIANT.
	(gfc_build_constant_array_constructor): Don't set TREE_INVARIANT.
	(gfc_conv_array_initializer): Don't set TREE_INVARIANT.
	* trans-common.c (get_init_field): Don't set TREE_INVARIANT.
	(create_common): Don't set TREE_INVARIANT.
	* trans-stmt.c (gfc_trans_character_select): Don't set TREE_INVARIANT.
	* trans-decl.c (gfc_generate_function_code): Don't set TREE_INVARIANT.


Index: tree.c
===================================================================
--- tree.c	(revision 133899)
+++ tree.c	(working copy)
@@ -621,7 +621,6 @@ make_node_stat (enum tree_code code MEM_
 
     case tcc_constant:
       TREE_CONSTANT (t) = 1;
-      TREE_INVARIANT (t) = 1;
       break;
 
     case tcc_expression:
@@ -1192,7 +1191,6 @@ build_string (int len, const char *str)
   memset (s, 0, sizeof (struct tree_common));
   TREE_SET_CODE (s, STRING_CST);
   TREE_CONSTANT (s) = 1;
-  TREE_INVARIANT (s) = 1;
   TREE_STRING_LENGTH (s) = len;
   memcpy (s->string.str, str, len);
   s->string.str[len] = '\0';
@@ -2057,6 +2055,75 @@ staticp (tree arg)
     }
 }
 \f
+/* Return true if T is an invariant address.  */
+
+bool
+invariant_addr_p (const_tree t)
+{
+  tree op;
+
+  if (TREE_CODE (t) != ADDR_EXPR)
+    return false;
+
+  op = TREE_OPERAND (t, 0);
+  while (handled_component_p (op))
+    {
+      switch (TREE_CODE (op))
+	{
+	case ARRAY_REF:
+	case ARRAY_RANGE_REF:
+	  if (TREE_CODE (TREE_OPERAND (op, 1)) != INTEGER_CST
+	      || TREE_OPERAND (op, 2) != NULL_TREE
+	      || TREE_OPERAND (op, 3) != NULL_TREE)
+	    return false;
+	  break;
+
+	case COMPONENT_REF:
+	  if (TREE_OPERAND (op, 2) != NULL_TREE)
+	    return false;
+	  break;
+
+	default:;
+	}
+      op = TREE_OPERAND (op, 0);
+    }
+
+  if (CONSTANT_CLASS_P (op))
+    return true;
+
+  if (INDIRECT_REF_P (op))
+    return false;
+
+  switch (TREE_CODE (op))
+    {
+    case PARM_DECL:
+    case RESULT_DECL:
+    case LABEL_DECL:
+    case FUNCTION_DECL:
+      return true;
+
+    case VAR_DECL:
+      if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+	   && ! DECL_DLLIMPORT_P (op))
+	  || DECL_THREAD_LOCAL_P (op)
+	  || DECL_CONTEXT (op) == current_function_decl
+	  || decl_function_context (op) == current_function_decl)
+	return true;
+      break;
+
+    case CONST_DECL:
+      if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
+	  || decl_function_context (op) == current_function_decl)
+	return true;
+      break;
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
 /* Wrap a SAVE_EXPR around EXPR, if appropriate.
    Do this to any expression which may be used in more than one place,
    but must be evaluated only once.
@@ -2092,8 +2159,9 @@ save_expr (tree expr)
      literal node.  */
   inner = skip_simple_arithmetic (t);
 
-  if (TREE_INVARIANT (inner)
+  if (TREE_CONSTANT (inner)
       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
+      || (TREE_CODE (inner) == ADDR_EXPR && invariant_addr_p (inner))
       || TREE_CODE (inner) == SAVE_EXPR
       || TREE_CODE (inner) == ERROR_MARK)
     return t;
@@ -2116,7 +2184,6 @@ save_expr (tree expr)
      value was computed on both sides of the jump.  So make sure it isn't
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
-  TREE_INVARIANT (t) = 1;
   return t;
 }
 
@@ -2144,9 +2211,11 @@ skip_simple_arithmetic (tree expr)
 	inner = TREE_OPERAND (inner, 0);
       else if (BINARY_CLASS_P (inner))
 	{
-	  if (TREE_INVARIANT (TREE_OPERAND (inner, 1)))
+	  if (TREE_CONSTANT (TREE_OPERAND (inner, 1))
+	      || TREE_CODE (TREE_OPERAND (inner, 1)) == SAVE_EXPR)
 	    inner = TREE_OPERAND (inner, 0);
-	  else if (TREE_INVARIANT (TREE_OPERAND (inner, 0)))
+	  else if (TREE_CONSTANT (TREE_OPERAND (inner, 0))
+	           || TREE_CODE (TREE_OPERAND (inner, 0)) == SAVE_EXPR)
 	    inner = TREE_OPERAND (inner, 1);
 	  else
 	    break;
@@ -2815,7 +2884,7 @@ stabilize_reference_1 (tree e)
      ignore things that are actual constant or that already have been
      handled by this function.  */
 
-  if (TREE_INVARIANT (e))
+  if (TREE_CONSTANT (e))
     return e;
 
   switch (TREE_CODE_CLASS (code))
@@ -2868,7 +2937,6 @@ stabilize_reference_1 (tree e)
   TREE_READONLY (result) = TREE_READONLY (e);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
-  TREE_INVARIANT (result) = 1;
 
   return result;
 }
@@ -2876,13 +2944,13 @@ stabilize_reference_1 (tree e)
 /* Low-level constructors for expressions.  */
 
 /* A helper function for build1 and constant folders.  Set TREE_CONSTANT,
-   TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
+   and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
 
 void
 recompute_tree_invariant_for_addr_expr (tree t)
 {
   tree node;
-  bool tc = true, ti = true, se = false;
+  bool tc = true, se = false;
 
   /* We started out assuming this address is both invariant and constant, but
      does not have side effects.  Now go down any handled components and see if
@@ -2892,9 +2960,8 @@ recompute_tree_invariant_for_addr_expr (
      ??? Note that this code makes no attempt to deal with the case where
      taking the address of something causes a copy due to misalignment.  */
 
-#define UPDATE_TITCSE(NODE)  \
+#define UPDATE_FLAGS(NODE)  \
 do { tree _node = (NODE); \
-     if (_node && !TREE_INVARIANT (_node)) ti = false; \
      if (_node && !TREE_CONSTANT (_node)) tc = false; \
      if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
 
@@ -2908,11 +2975,11 @@ do { tree _node = (NODE); \
 	   || TREE_CODE (node) == ARRAY_RANGE_REF)
 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
 	{
-	  UPDATE_TITCSE (TREE_OPERAND (node, 1));
+	  UPDATE_FLAGS (TREE_OPERAND (node, 1));
 	  if (TREE_OPERAND (node, 2))
-	    UPDATE_TITCSE (TREE_OPERAND (node, 2));
+	    UPDATE_FLAGS (TREE_OPERAND (node, 2));
 	  if (TREE_OPERAND (node, 3))
-	    UPDATE_TITCSE (TREE_OPERAND (node, 3));
+	    UPDATE_FLAGS (TREE_OPERAND (node, 3));
 	}
       /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
 	 FIELD_DECL, apparently.  The G++ front end can put something else
@@ -2921,46 +2988,35 @@ do { tree _node = (NODE); \
 	       && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
 	{
 	  if (TREE_OPERAND (node, 2))
-	    UPDATE_TITCSE (TREE_OPERAND (node, 2));
+	    UPDATE_FLAGS (TREE_OPERAND (node, 2));
 	}
       else if (TREE_CODE (node) == BIT_FIELD_REF)
-	UPDATE_TITCSE (TREE_OPERAND (node, 2));
+	UPDATE_FLAGS (TREE_OPERAND (node, 2));
     }
 
-  node = lang_hooks.expr_to_decl (node, &tc, &ti, &se);
+  node = lang_hooks.expr_to_decl (node, &tc, &se);
 
   /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
-     the address, since &(*a)->b is a form of addition.  If it's a decl, it's
-     invariant and constant if the decl is static.  It's also invariant if it's
-     a decl in the current function.  Taking the address of a volatile variable
-     is not volatile.  If it's a constant, the address is both invariant and
-     constant.  Otherwise it's neither.  */
+     the address, since &(*a)->b is a form of addition.  If it's a constant, the
+     address is constant too.  If it's a decl, its address is constant if the
+     decl is static.  Everything else is not constant and, furthermore,
+     taking the address of a volatile variable is not volatile.  */
   if (TREE_CODE (node) == INDIRECT_REF)
-    UPDATE_TITCSE (TREE_OPERAND (node, 0));
-  else if (DECL_P (node))
-    {
-      if (staticp (node))
-	;
-      else if (decl_function_context (node) == current_function_decl
-	       /* Addresses of thread-local variables are invariant.  */
-	       || (TREE_CODE (node) == VAR_DECL
-		   && DECL_THREAD_LOCAL_P (node)))
-	tc = false;
-      else
-	ti = tc = false;
-    }
+    UPDATE_FLAGS (TREE_OPERAND (node, 0));
   else if (CONSTANT_CLASS_P (node))
     ;
+  else if (DECL_P (node))
+    tc &= (staticp (node) != NULL_TREE);
   else
     {
-      ti = tc = false;
+      tc = false;
       se |= TREE_SIDE_EFFECTS (node);
     }
 
+
   TREE_CONSTANT (t) = tc;
-  TREE_INVARIANT (t) = ti;
   TREE_SIDE_EFFECTS (t) = se;
-#undef UPDATE_TITCSE
+#undef UPDATE_FLAGS
 }
 
 /* Build an expression of code CODE, data type TYPE, and operands as
@@ -3057,9 +3113,6 @@ build1_stat (enum tree_code code, tree t
 	  && node && !TYPE_P (node)
 	  && TREE_CONSTANT (node))
 	TREE_CONSTANT (t) = 1;
-      if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR)
-	  && node && TREE_INVARIANT (node))
-	TREE_INVARIANT (t) = 1;
       if (TREE_CODE_CLASS (code) == tcc_reference
 	  && node && TREE_THIS_VOLATILE (node))
 	TREE_THIS_VOLATILE (t) = 1;
@@ -3080,15 +3133,13 @@ build1_stat (enum tree_code code, tree t
 	  read_only = 0;		\
         if (!TREE_CONSTANT (arg##N))	\
 	  constant = 0;			\
-	if (!TREE_INVARIANT (arg##N))	\
-	  invariant = 0;		\
       }					\
   } while (0)
 
 tree
 build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 2);
@@ -3125,14 +3176,12 @@ build2_stat (enum tree_code code, tree t
 	      || TREE_CODE_CLASS (code) == tcc_binary);
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
-  invariant = constant;
 
   PROCESS_ARG(0);
   PROCESS_ARG(1);
 
   TREE_READONLY (t) = read_only;
   TREE_CONSTANT (t) = constant;
-  TREE_INVARIANT (t) = invariant;
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
     = (TREE_CODE_CLASS (code) == tcc_reference
@@ -3161,7 +3210,7 @@ tree
 build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 	     tree arg2 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 3);
@@ -3197,7 +3246,7 @@ tree
 build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 	     tree arg2, tree arg3 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 4);
@@ -3224,7 +3273,7 @@ tree
 build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 	     tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 5);
@@ -3253,7 +3302,7 @@ build7_stat (enum tree_code code, tree t
 	     tree arg2, tree arg3, tree arg4, tree arg5,
 	     tree arg6 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (code == TARGET_MEM_REF);
@@ -3883,8 +3932,7 @@ merge_dllimport_decl_attributes (tree ol
 		   "after being referenced with dll linkage", new);
 	  /* If we have used a variable's address with dllimport linkage,
 	      keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
-	      decl may already have had TREE_INVARIANT and TREE_CONSTANT
-	      computed.
+	      decl may already have had TREE_CONSTANT computed.
 	      We still remove the attribute so that assembler code refers
 	      to '&foo rather than '_imp__foo'.  */
 	  if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
Index: tree.h
===================================================================
--- tree.h	(revision 133899)
+++ tree.h	(working copy)
@@ -387,7 +387,6 @@ struct tree_base GTY(())
   unsigned private_flag : 1;
   unsigned protected_flag : 1;
   unsigned deprecated_flag : 1;
-  unsigned invariant_flag : 1;
   unsigned saturating_flag : 1;
 
   unsigned lang_flag_0 : 1;
@@ -399,7 +398,7 @@ struct tree_base GTY(())
   unsigned lang_flag_6 : 1;
   unsigned visited : 1;
 
-  unsigned spare : 23;
+  unsigned spare : 24;
 
   /* FIXME tuples: Eventually, we need to move this somewhere external to
      the trees.  */
@@ -578,11 +577,6 @@ struct gimple_stmt GTY(())
 
    	Used in tree traversals to mark visited nodes.
 
-   invariant_flag:
-
-	TREE_INVARIANT in
-	    all expressions.
-
    saturating_flag:
 
        TYPE_SATURATING in
@@ -1371,12 +1365,6 @@ extern void omp_clause_range_check_faile
 #define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
   (IDENTIFIER_NODE_CHECK (NODE)->base.deprecated_flag)
 
-/* Value of expression is function invariant.  A strict subset of
-   TREE_CONSTANT, such an expression is constant over any one function
-   invocation, though not across different invocations.  May appear in
-   any expression node.  */
-#define TREE_INVARIANT(NODE) ((NODE)->base.invariant_flag)
-
 /* In fixed-point types, means a saturating type.  */
 #define TYPE_SATURATING(NODE) ((NODE)->base.saturating_flag)
 
@@ -4887,6 +4875,7 @@ extern tree strip_float_extensions (tree
 
 /* In tree.c */
 extern int really_constant_p (const_tree);
+extern bool invariant_addr_p (const_tree);
 extern int int_fits_type_p (const_tree, const_tree);
 #ifndef GENERATOR_FILE
 extern void get_type_static_bounds (const_tree, mpz_t, mpz_t);
Index: builtins.c
===================================================================
--- builtins.c	(revision 133899)
+++ builtins.c	(working copy)
@@ -5236,7 +5236,6 @@ build_string_literal (int len, const cha
   type = build_array_type (elem, index);
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = 1;
-  TREE_INVARIANT (t) = 1;
   TREE_READONLY (t) = 1;
   TREE_STATIC (t) = 1;
 
@@ -7150,7 +7149,7 @@ fold_builtin_expect (tree arg0, tree arg
     }
 
   /* If the argument isn't invariant then there's nothing else we can do.  */
-  if (!TREE_INVARIANT (arg0))
+  if (!TREE_CONSTANT (arg0))
     return NULL_TREE;
 
   /* If we expect that a comparison against the argument will fold to
Index: tree-gimple.c
===================================================================
--- tree-gimple.c	(revision 133899)
+++ tree-gimple.c	(working copy)
@@ -57,12 +57,14 @@ is_gimple_formal_tmp_rhs (tree t)
 
   switch (code)
     {
+    case ADDR_EXPR:
+      return is_gimple_address (t);
+
     case TRUTH_NOT_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
     case COND_EXPR:
-    case ADDR_EXPR:
     case CALL_EXPR:
     case CONSTRUCTOR:
     case COMPLEX_EXPR:
@@ -197,7 +199,7 @@ is_gimple_constant (const_tree t)
 /* Return true if T is a gimple invariant address.  */
 
 bool
-is_gimple_invariant_address (const_tree t)
+is_gimple_address (const_tree t)
 {
   tree op;
 
@@ -206,61 +208,24 @@ is_gimple_invariant_address (const_tree 
 
   op = TREE_OPERAND (t, 0);
   while (handled_component_p (op))
-    {
-      switch (TREE_CODE (op))
-	{
-	case ARRAY_REF:
-	case ARRAY_RANGE_REF:
-	  if (!is_gimple_constant (TREE_OPERAND (op, 1))
-	      || TREE_OPERAND (op, 2) != NULL_TREE
-	      || TREE_OPERAND (op, 3) != NULL_TREE)
-	    return false;
-	  break;
-
-	case COMPONENT_REF:
-	  if (TREE_OPERAND (op, 2) != NULL_TREE)
-	    return false;
-	  break;
-
-	default:;
-	}
-      op = TREE_OPERAND (op, 0);
-    }
+    op = TREE_OPERAND (op, 0);
 
-  if (CONSTANT_CLASS_P (op))
+  if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
     return true;
 
-  if (INDIRECT_REF_P (op))
-    return false;
-
   switch (TREE_CODE (op))
     {
     case PARM_DECL:
     case RESULT_DECL:
     case LABEL_DECL:
     case FUNCTION_DECL:
-      return true;
-
     case VAR_DECL:
-      if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
-	   && ! DECL_DLLIMPORT_P (op))
-	  || DECL_THREAD_LOCAL_P (op)
-	  || DECL_CONTEXT (op) == current_function_decl
-	  || decl_function_context (op) == current_function_decl)
-	return true;
-      break;
-
     case CONST_DECL:
-      if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
-	  || decl_function_context (op) == current_function_decl)
-	return true;
-      break;
+      return true;
 
     default:
-      gcc_unreachable ();
+      return false;
     }
-
-  return false;
 }
 
 /* Return true if T is a GIMPLE minimal invariant.  It's a restricted
@@ -270,7 +235,7 @@ bool
 is_gimple_min_invariant (const_tree t)
 {
   if (TREE_CODE (t) == ADDR_EXPR)
-    return is_gimple_invariant_address (t);
+    return invariant_addr_p (t);
 
   return is_gimple_constant (t);
 }
Index: tree-gimple.h
===================================================================
--- tree-gimple.h	(revision 133899)
+++ tree-gimple.h	(working copy)
@@ -62,8 +62,8 @@ extern bool is_gimple_addressable (tree)
 /* Returns true iff T is any valid GIMPLE lvalue.  */
 extern bool is_gimple_lvalue (tree);
 
-/* Returns true iff T is a GIMPLE invariant address.  */
-bool is_gimple_invariant_address (const_tree);
+/* Returns true iff T is a valid GIMPLE address.  */
+bool is_gimple_address (const_tree);
 /* Returns true iff T is a valid GIMPLE constant.  */
 bool is_gimple_constant (const_tree);
 /* Returns true iff T is a GIMPLE restricted function invariant.  */
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 133899)
+++ tree-ssa-ccp.c	(working copy)
@@ -2097,8 +2097,8 @@ fold_stmt_r (tree *expr_p, int *walk_sub
 	return t;
       *walk_subtrees = 0;
 
-      /* Set TREE_INVARIANT properly so that the value is properly
-	 considered constant, and so gets propagated as expected.  */
+      /* Make sure the value is properly considered constant, and so gets
+	 propagated as expected.  */
       if (*changed_p)
         recompute_tree_invariant_for_addr_expr (expr);
       return NULL_TREE;
Index: c-tree.h
===================================================================
--- c-tree.h	(revision 133899)
+++ c-tree.h	(working copy)
@@ -593,7 +593,7 @@ extern tree c_finish_goto_label (tree);
 extern tree c_finish_goto_ptr (tree);
 extern void c_begin_vm_scope (unsigned int);
 extern void c_end_vm_scope (unsigned int);
-extern tree c_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree c_expr_to_decl (tree, bool *, bool *);
 extern tree c_begin_omp_parallel (void);
 extern tree c_finish_omp_parallel (tree, tree);
 extern tree c_finish_omp_clauses (tree);
Index: langhooks.c
===================================================================
--- langhooks.c	(revision 133899)
+++ langhooks.c	(working copy)
@@ -502,8 +502,7 @@ lhd_to_target_charset (HOST_WIDE_INT c)
 }
 
 tree
-lhd_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
-		  bool *ti ATTRIBUTE_UNUSED, bool *se ATTRIBUTE_UNUSED)
+lhd_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se ATTRIBUTE_UNUSED)
 {
   return expr;
 }
Index: langhooks.h
===================================================================
--- langhooks.h	(revision 133900)
+++ langhooks.h	(working copy)
@@ -400,10 +400,9 @@ struct lang_hooks
   void (*init_ts) (void);
 
   /* Called by recompute_tree_invariant_for_addr_expr to go from EXPR
-     to a contained expression or DECL, possibly updating *TC, *TI or
-     *SE if in the process TREE_CONSTANT, TREE_INVARIANT or
-     TREE_SIDE_EFFECTS need updating.  */
-  tree (*expr_to_decl) (tree expr, bool *tc, bool *ti, bool *se);
+     to a contained expression or DECL, possibly updating *TC or *SE
+     if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
+  tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
 
   /* Whenever you add entries here, make sure you adjust langhooks-def.h
      and langhooks.c accordingly.  */
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 133899)
+++ c-typeck.c	(working copy)
@@ -2213,7 +2213,6 @@ build_external_ref (tree id, int fun, lo
       used_types_insert (TREE_TYPE (ref));
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
-      TREE_INVARIANT (ref) = 1;
     }
   else if (current_function_decl != 0
 	   && !DECL_FILE_SCOPE_P (current_function_decl)
@@ -3643,7 +3642,6 @@ build_c_cast (tree type, tree expr)
 			   build_constructor_single (type, field, value),
 			   true, 0);
 	  TREE_CONSTANT (t) = TREE_CONSTANT (value);
-	  TREE_INVARIANT (t) = TREE_INVARIANT (value);
 	  return t;
 	}
       error ("cast to union type from type not present in union");
@@ -5608,7 +5606,7 @@ pop_init_level (int implicit)
 	  ret.value = build_constructor (constructor_type,
 					 constructor_elements);
 	  if (constructor_constant)
-	    TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
+	    TREE_CONSTANT (ret.value) = 1;
 	  if (constructor_constant && constructor_simple)
 	    TREE_STATIC (ret.value) = 1;
 	}
@@ -8655,8 +8653,7 @@ c_objc_common_truthvalue_conversion (tre
    required.  */
 
 tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
-		bool *ti ATTRIBUTE_UNUSED, bool *se)
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
 {
   if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
     {
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 133899)
+++ gimplify.c	(working copy)
@@ -2868,12 +2868,14 @@ gimplify_init_ctor_preeval (tree *expr_p
 {
   enum gimplify_status one;
 
-  /* If the value is invariant, then there's nothing to pre-evaluate.
-     But ensure it doesn't have any side-effects since a SAVE_EXPR is
-     invariant but has side effects and might contain a reference to
-     the object we're initializing.  */
-  if (TREE_INVARIANT (*expr_p) && !TREE_SIDE_EFFECTS (*expr_p))
-    return;
+  /* If the value is constant, then there's nothing to pre-evaluate.  */
+  if (TREE_CONSTANT (*expr_p))
+    {
+      /* Ensure it does not have side effects, it might contain a reference to
+	 the object we're initializing.  */
+      gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
+      return;
+    }
 
   /* If the type has non-trivial constructors, we can't pre-evaluate.  */
   if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
@@ -3416,7 +3418,6 @@ gimplify_init_constructor (tree *expr_p,
 	      break;
 
 	    TREE_CONSTANT (ctor) = 0;
-	    TREE_INVARIANT (ctor) = 0;
 	  }
 
 	/* Vector types use CONSTRUCTOR all the way through gimple
@@ -4254,8 +4255,7 @@ gimplify_addr_expr (tree *expr_p, tree *
 	  if (TREE_CODE (op0) == INDIRECT_REF)
 	    goto do_indirect_ref;
 
-	  /* Make sure TREE_INVARIANT, TREE_CONSTANT, and TREE_SIDE_EFFECTS
-	     is set properly.  */
+	  /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly.  */
 	  recompute_tree_invariant_for_addr_expr (expr);
 
 	  mark_addressable (TREE_OPERAND (expr, 0));
Index: tree-mudflap.c
===================================================================
--- tree-mudflap.c	(revision 133899)
+++ tree-mudflap.c	(working copy)
@@ -83,7 +83,6 @@ mf_build_string (const char *string)
   TREE_TYPE (result) = build_array_type
     (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
   TREE_CONSTANT (result) = 1;
-  TREE_INVARIANT (result) = 1;
   TREE_READONLY (result) = 1;
   TREE_STATIC (result) = 1;
 
Index: print-tree.c
===================================================================
--- print-tree.c	(revision 133899)
+++ print-tree.c	(working copy)
@@ -292,8 +292,6 @@ print_node (FILE *file, const char *pref
   else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
     fputs (" sizes-gimplified", file);
 
-  if (TREE_INVARIANT (node))
-    fputs (" invariant", file);
   if (TREE_ADDRESSABLE (node))
     fputs (" addressable", file);
   if (TREE_THIS_VOLATILE (node))
Index: tree-nested.c
===================================================================
--- tree-nested.c	(revision 133899)
+++ tree-nested.c	(working copy)
@@ -1037,8 +1037,8 @@ convert_nonlocal_reference (tree *tp, in
 	  {
 	    tree save_context;
 
-	    /* If we changed anything, then TREE_INVARIANT is be wrong,
-	       since we're no longer directly referencing a decl.  */
+	    /* If we changed anything, we might no longer be directly
+	       referencing a decl.  */
 	    save_context = current_function_decl;
 	    current_function_decl = info->context;
 	    recompute_tree_invariant_for_addr_expr (t);
Index: c-common.c
===================================================================
--- c-common.c	(revision 133899)
+++ c-common.c	(working copy)
@@ -907,7 +907,6 @@ fix_string_type (tree value)
 
   TREE_TYPE (value) = a_type;
   TREE_CONSTANT (value) = 1;
-  TREE_INVARIANT (value) = 1;
   TREE_READONLY (value) = 1;
   TREE_STATIC (value) = 1;
   return value;
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 133900)
+++ tree-cfg.c	(working copy)
@@ -3161,28 +3161,20 @@ verify_expr (tree *tp, int *walk_subtree
 
     case ADDR_EXPR:
       {
-	bool old_invariant;
 	bool old_constant;
 	bool old_side_effects;
-	bool new_invariant;
 	bool new_constant;
 	bool new_side_effects;
 
-	old_invariant = TREE_INVARIANT (t);
+	gcc_assert (is_gimple_address (t));
+
 	old_constant = TREE_CONSTANT (t);
 	old_side_effects = TREE_SIDE_EFFECTS (t);
 
 	recompute_tree_invariant_for_addr_expr (t);
-	new_invariant = TREE_INVARIANT (t);
 	new_side_effects = TREE_SIDE_EFFECTS (t);
 	new_constant = TREE_CONSTANT (t);
 
-	if (old_invariant != new_invariant)
-	  {
-	    error ("invariant not recomputed when ADDR_EXPR changed");
-	    return t;
-	  }
-
         if (old_constant != new_constant)
 	  {
 	    error ("constant not recomputed when ADDR_EXPR changed");
Index: langhooks-def.h
===================================================================
--- langhooks-def.h	(revision 133900)
+++ langhooks-def.h	(working copy)
@@ -64,7 +64,7 @@ extern const char *lhd_comdat_group (tre
 extern tree lhd_expr_size (const_tree);
 extern size_t lhd_tree_size (enum tree_code);
 extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
-extern tree lhd_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree lhd_expr_to_decl (tree, bool *, bool *);
 extern tree lhd_builtin_function (tree decl);
 
 /* Declarations of default tree inlining hooks.  */
Index: java/class.c
===================================================================
--- java/class.c	(revision 133899)
+++ java/class.c	(working copy)
@@ -955,7 +955,6 @@ build_utf8_ref (tree name)
   PUSH_FIELD_VALUE (cinit, "data", string);
   FINISH_RECORD_CONSTRUCTOR (cinit);
   TREE_CONSTANT (cinit) = 1;
-  TREE_INVARIANT (cinit) = 1;
 
   /* Generate a unique-enough identifier.  */
   sprintf(buf, "_Utf%d", ++utf8_count);
@@ -1063,7 +1062,6 @@ build_classdollar_field (tree type)
 					     /* const */ 1, 0)),
 			/* const */ 1, 0)));
       TREE_STATIC (decl) = 1;
-      TREE_INVARIANT (decl) = 1;
       TREE_CONSTANT (decl) = 1;
       TREE_READONLY (decl) = 1;
       TREE_PUBLIC (decl) = 1;
@@ -1604,7 +1602,6 @@ get_dispatch_table (tree type, tree this
 		tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node, 
 				     method, build_int_cst (NULL_TREE, j));
 		TREE_CONSTANT (fdesc) = 1;
-		TREE_INVARIANT (fdesc) = 1;
 	        list = tree_cons (NULL_TREE, fdesc, list);
 	      }
 	  else
@@ -2076,7 +2073,6 @@ make_class_data (tree type)
 			build1 (ADDR_EXPR, symbols_array_ptr_type,
 				TYPE_OTABLE_SYMS_DECL (type)));
       TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_OTABLE_DECL (type)) = 1;
     }
   if (TYPE_ATABLE_METHODS(type) == NULL_TREE)
     {
@@ -2092,7 +2088,6 @@ make_class_data (tree type)
 			build1 (ADDR_EXPR, symbols_array_ptr_type,
 				TYPE_ATABLE_SYMS_DECL (type)));
       TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1;
     }
    if (TYPE_ITABLE_METHODS(type) == NULL_TREE)
     {
@@ -2108,7 +2103,6 @@ make_class_data (tree type)
 			build1 (ADDR_EXPR, symbols_array_ptr_type,
 				TYPE_ITABLE_SYMS_DECL (type)));
       TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1;
-      TREE_INVARIANT (TYPE_ITABLE_DECL (type)) = 1;
     }
  
   PUSH_FIELD_VALUE (cons, "catch_classes",
@@ -2848,7 +2842,6 @@ build_symbol_entry (tree decl, tree spec
   PUSH_FIELD_VALUE (sym, "signature", signature);
   FINISH_RECORD_CONSTRUCTOR (sym);
   TREE_CONSTANT (sym) = 1;
-  TREE_INVARIANT (sym) = 1;
 
   return sym;
 } 
@@ -2889,7 +2882,6 @@ emit_symbol_table (tree name, tree the_t
   PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
   FINISH_RECORD_CONSTRUCTOR (null_symbol);
   TREE_CONSTANT (null_symbol) = 1;  
-  TREE_INVARIANT (null_symbol) = 1;  
   list = tree_cons (NULL_TREE, null_symbol, list);
 
   /* Put the list in the right order and make it a constructor. */
Index: java/constants.c
===================================================================
--- java/constants.c	(revision 133899)
+++ java/constants.c	(working copy)
@@ -445,7 +445,6 @@ build_constant_data_ref (bool indirect)
       TREE_THIS_NOTRAP (klass) = 1;
       data = fold_convert (build_pointer_type (cpool_type), data);
       d = build1 (INDIRECT_REF, cpool_type, data);
-      TREE_INVARIANT (d) = 1;
 
       return d;
     }
@@ -485,7 +484,6 @@ build_ref_from_constant_pool (int index)
   i = build_int_cst (NULL_TREE, index);
   d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
 		 NULL_TREE, NULL_TREE);
-  TREE_INVARIANT (d) = 1;
   return d;
 }
 
Index: java/resource.c
===================================================================
--- java/resource.c	(revision 133899)
+++ java/resource.c	(working copy)
@@ -73,7 +73,6 @@ compile_resource_data (const char *name,
   PUSH_FIELD_VALUE (rinit, "data", data);
   FINISH_RECORD_CONSTRUCTOR (rinit);
   TREE_CONSTANT (rinit) = 1;
-  TREE_INVARIANT (rinit) = 1;
 
   decl = build_decl (VAR_DECL, java_mangle_resource_name (name), rtype);
   TREE_STATIC (decl) = 1;
Index: java/expr.c
===================================================================
--- java/expr.c	(revision 133899)
+++ java/expr.c	(working copy)
@@ -3809,7 +3809,6 @@ cache_cpool_data_ref (void)
       tree cpool_ptr = build_decl (VAR_DECL, NULL_TREE, 
 				   build_pointer_type (TREE_TYPE (d)));
       java_add_local_var (cpool_ptr);
-      TREE_INVARIANT (cpool_ptr) = 1;
       TREE_CONSTANT (cpool_ptr) = 1;
 
       java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (cpool_ptr), 
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 133899)
+++ objc/objc-act.c	(working copy)
@@ -1953,7 +1953,6 @@ objc_build_string_object (tree string)
  			    initlist);
       constructor = objc_build_constructor (internal_const_str_type,
 					    nreverse (initlist));
-      TREE_INVARIANT (constructor) = true;
 
       if (!flag_next_runtime)
 	constructor
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 133899)
+++ cp/typeck.c	(working copy)
@@ -2764,7 +2764,6 @@ get_member_function_from_ptrfunc (tree *
 			fold_convert (sizetype, idx));
       e2 = cp_build_indirect_ref (e2, NULL, tf_warning_or_error);
       TREE_CONSTANT (e2) = 1;
-      TREE_INVARIANT (e2) = 1;
 
       /* When using function descriptors, the address of the
 	 vtable entry is treated as a function pointer.  */
@@ -6394,7 +6393,6 @@ build_ptrmemfunc1 (tree type, tree delta
   CONSTRUCTOR_APPEND_ELT(v, delta_field, delta);
   u = build_constructor (type, v);
   TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
-  TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta);
   TREE_STATIC (u) = (TREE_CONSTANT (u)
 		     && (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
 			 != NULL_TREE)
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 133899)
+++ cp/init.c	(working copy)
@@ -261,10 +261,7 @@ build_zero_init (tree type, tree nelts, 
 
   /* In all cases, the initializer is a constant.  */
   if (init)
-    {
-      TREE_CONSTANT (init) = 1;
-      TREE_INVARIANT (init) = 1;
-    }
+    TREE_CONSTANT (init) = 1;
 
   return init;
 }
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 133899)
+++ cp/class.c	(working copy)
@@ -385,7 +385,6 @@ build_base_path (enum tree_code code,
 			 v_offset);
       v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error);
       TREE_CONSTANT (v_offset) = 1;
-      TREE_INVARIANT (v_offset) = 1;
 
       offset = convert_to_integer (ptrdiff_type_node,
 				   size_diffop (offset,
@@ -630,7 +629,6 @@ build_vtbl_ref_1 (tree instance, tree id
 
   aref = build_array_ref (vtbl, idx);
   TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
-  TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
 
   return aref;
 }
@@ -7448,7 +7446,6 @@ build_vtbl_initializer (tree binfo,
 				     TREE_OPERAND (init, 0),
 				     build_int_cst (NULL_TREE, i));
 		TREE_CONSTANT (fdesc) = 1;
-		TREE_INVARIANT (fdesc) = 1;
 
 		vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
 	      }
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 133900)
+++ cp/decl.c	(working copy)
@@ -10957,7 +10957,6 @@ build_enumerator (tree name, tree value,
 
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
   TREE_CONSTANT (decl) = 1;
-  TREE_INVARIANT (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_INITIAL (decl) = value;
 
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 133899)
+++ cp/rtti.c	(working copy)
@@ -902,7 +902,6 @@ tinfo_base_init (tinfo_s *ti, tree targe
 
   init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   init = tree_cons (NULL_TREE, init, NULL_TREE);
 
@@ -920,7 +919,6 @@ generic_initializer (tinfo_s *ti, tree t
 
   init = build_constructor_from_list (NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -946,7 +944,6 @@ ptr_initializer (tinfo_s *ti, tree targe
 
   init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -979,7 +976,6 @@ ptm_initializer (tinfo_s *ti, tree targe
 
   init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -996,7 +992,6 @@ class_initializer (tinfo_s *ti, tree tar
   TREE_CHAIN (init) = trail;
   init = build_constructor_from_list (NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 133899)
+++ cp/typeck2.c	(working copy)
@@ -1081,7 +1081,6 @@ process_init_constructor (tree type, tre
   if (!(flags & PICFLAG_NOT_ALL_CONSTANT))
     {
       TREE_CONSTANT (init) = 1;
-      TREE_INVARIANT (init) = 1;
       if (!(flags & PICFLAG_NOT_ALL_SIMPLE))
 	TREE_STATIC (init) = 1;
     }
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 133899)
+++ cp/pt.c	(working copy)
@@ -384,7 +384,6 @@ push_inline_template_parms_recursive (tr
 				    TREE_TYPE (parm));
 	    DECL_ARTIFICIAL (decl) = 1;
 	    TREE_CONSTANT (decl) = 1;
-	    TREE_INVARIANT (decl) = 1;
 	    TREE_READONLY (decl) = 1;
 	    DECL_INITIAL (decl) = DECL_INITIAL (parm);
 	    SET_DECL_TEMPLATE_PARM_P (decl);
@@ -2870,7 +2869,6 @@ build_template_parm_index (int index,
   TEMPLATE_PARM_DECL (t) = decl;
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = TREE_CONSTANT (decl);
-  TREE_INVARIANT (t) = TREE_INVARIANT (decl);
   TREE_READONLY (t) = TREE_READONLY (decl);
 
   return t;
@@ -2923,7 +2921,6 @@ reduce_template_parm_level (tree index, 
 
       decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
       TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
-      TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
       TREE_READONLY (decl) = TREE_READONLY (orig_decl);
       DECL_ARTIFICIAL (decl) = 1;
       SET_DECL_TEMPLATE_PARM_P (decl);
@@ -3020,11 +3017,9 @@ process_template_parm (tree list, tree p
 
       /* A template parameter is not modifiable.  */
       TREE_CONSTANT (parm) = 1;
-      TREE_INVARIANT (parm) = 1;
       TREE_READONLY (parm) = 1;
       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
       TREE_CONSTANT (decl) = 1;
-      TREE_INVARIANT (decl) = 1;
       TREE_READONLY (decl) = 1;
       DECL_INITIAL (parm) = DECL_INITIAL (decl)
 	= build_template_parm_index (idx, processing_template_decl,
Index: ada/trans.c
===================================================================
--- ada/trans.c	(revision 133899)
+++ ada/trans.c	(working copy)
@@ -1234,7 +1234,6 @@ Attribute_to_gnu (Node_Id gnat_node, tre
 	    gnu_result
 	      = build1 (SAVE_EXPR, TREE_TYPE (gnu_result), gnu_result);
 	    TREE_SIDE_EFFECTS (gnu_result) = 1;
-	    TREE_INVARIANT (gnu_result) = 1;
 	    if (attribute == Attr_First)
 	      pa->first = gnu_result;
 	    else if (attribute == Attr_Last)
@@ -2174,7 +2173,6 @@ call_to_gnu (Node_Id gnat_node, tree *gn
 	     used as the object and copied back after the call if needed.  */
 	  gnu_name = build1 (SAVE_EXPR, TREE_TYPE (gnu_name), gnu_name);
 	  TREE_SIDE_EFFECTS (gnu_name) = 1;
-	  TREE_INVARIANT (gnu_name) = 1;
 
 	  /* Set up to move the copy back to the original.  */
 	  if (Ekind (gnat_formal) != E_In_Parameter)
Index: ada/utils2.c
===================================================================
--- ada/utils2.c	(revision 133899)
+++ ada/utils2.c	(working copy)
@@ -1656,8 +1656,7 @@ gnat_build_constructor (tree type, tree 
     }
 
   result = build_constructor_from_list (type, list);
-  TREE_CONSTANT (result) = TREE_INVARIANT (result)
-    = TREE_STATIC (result) = allconstant;
+  TREE_CONSTANT (result) = TREE_STATIC (result) = allconstant;
   TREE_SIDE_EFFECTS (result) = side_effects;
   TREE_READONLY (result) = TYPE_READONLY (type) || allconstant;
   return result;
Index: fortran/trans-expr.c
===================================================================
--- fortran/trans-expr.c	(revision 133899)
+++ fortran/trans-expr.c	(working copy)
@@ -3478,10 +3478,7 @@ gfc_conv_structure (gfc_se * se, gfc_exp
     }
   se->expr = build_constructor (type, v);
   if (init) 
-    {
-      TREE_CONSTANT(se->expr) = 1;
-      TREE_INVARIANT(se->expr) = 1;
-    }
+    TREE_CONSTANT (se->expr) = 1;
 }
 
 
Index: fortran/trans-array.c
===================================================================
--- fortran/trans-array.c	(revision 133899)
+++ fortran/trans-array.c	(working copy)
@@ -316,7 +316,6 @@ gfc_build_null_descriptor (tree type)
   /* Set a NULL data pointer.  */
   tmp = build_constructor_single (type, field, null_pointer_node);
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   /* All other fields are ignored.  */
 
   return tmp;
@@ -1207,13 +1206,11 @@ gfc_trans_array_constructor_value (stmtb
 
 	      init = build_constructor_from_list (tmptype, nreverse (list));
 	      TREE_CONSTANT (init) = 1;
-	      TREE_INVARIANT (init) = 1;
 	      TREE_STATIC (init) = 1;
 	      /* Create a static variable to hold the data.  */
 	      tmp = gfc_create_var (tmptype, "data");
 	      TREE_STATIC (tmp) = 1;
 	      TREE_CONSTANT (tmp) = 1;
-	      TREE_INVARIANT (tmp) = 1;
 	      TREE_READONLY (tmp) = 1;
 	      DECL_INITIAL (tmp) = init;
 	      init = tmp;
@@ -1582,13 +1579,11 @@ gfc_build_constant_array_constructor (gf
   init = build_constructor_from_list (tmptype, nreverse (list));
 
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
 
   tmp = gfc_create_var (tmptype, "A");
   TREE_STATIC (tmp) = 1;
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   TREE_READONLY (tmp) = 1;
   DECL_INITIAL (tmp) = init;
 
@@ -3885,7 +3880,6 @@ gfc_conv_array_initializer (tree type, g
   /* Create a constructor from the list of elements.  */
   tmp = build_constructor (type, v);
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   return tmp;
 }
 
Index: fortran/trans-common.c
===================================================================
--- fortran/trans-common.c	(revision 133899)
+++ fortran/trans-common.c	(working copy)
@@ -547,7 +547,6 @@ get_init_field (segment_info *head, tree
 
   init = build_constructor (TREE_TYPE (field), v);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
 
   *field_init = init;
 
@@ -657,7 +656,6 @@ create_common (gfc_common_head *com, seg
       gcc_assert (!VEC_empty (constructor_elt, v));
       ctor = build_constructor (union_type, v);
       TREE_CONSTANT (ctor) = 1;
-      TREE_INVARIANT (ctor) = 1;
       TREE_STATIC (ctor) = 1;
       DECL_INITIAL (decl) = ctor;
 
Index: fortran/trans-stmt.c
===================================================================
--- fortran/trans-stmt.c	(revision 133899)
+++ fortran/trans-stmt.c	(working copy)
@@ -1435,12 +1435,10 @@ gfc_trans_character_select (gfc_code *co
 
   init = build_constructor_from_list (type, nreverse(init));
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   /* Create a static variable to hold the jump table.  */
   tmp = gfc_create_var (type, "jumptable");
   TREE_CONSTANT (tmp) = 1;
-  TREE_INVARIANT (tmp) = 1;
   TREE_STATIC (tmp) = 1;
   TREE_READONLY (tmp) = 1;
   DECL_INITIAL (tmp) = init;
Index: fortran/trans-decl.c
===================================================================
--- fortran/trans-decl.c	(revision 133899)
+++ fortran/trans-decl.c	(working copy)
@@ -3185,13 +3185,11 @@ gfc_generate_function_code (gfc_namespac
 								      6)));
       array = build_constructor_from_list (array_type, nreverse (array));
       TREE_CONSTANT (array) = 1;
-      TREE_INVARIANT (array) = 1;
       TREE_STATIC (array) = 1;
 
       /* Create a static variable to hold the jump table.  */
       var = gfc_create_var (array_type, "options");
       TREE_CONSTANT (var) = 1;
-      TREE_INVARIANT (var) = 1;
       TREE_STATIC (var) = 1;
       TREE_READONLY (var) = 1;
       DECL_INITIAL (var) = array;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-05 12:46         ` Richard Guenther
  2008-04-05 14:35           ` Paolo Bonzini
@ 2008-04-09  1:00           ` Mark Mitchell
  2008-04-09 10:55             ` Paolo Bonzini
  1 sibling, 1 reply; 14+ messages in thread
From: Mark Mitchell @ 2008-04-09  1:00 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Paolo Bonzini, Eric Botcazou, gcc-patches

Richard Guenther wrote:

> Not really, but maybe the FEs depend on things like
> 
> const int i = 5;
> &a[i]
> 
> being an invariant address?

It's good to check that things work OK with -O0, but I think that if the 
FEs depend on this, that's broken.  TREE_INVARIANT is about what GCC can 
prove; not what any language standard says.  I think the FEs should be 
using language-specific flags that correspond to language-specific 
concepts (like C++'s "integral constant expressions").

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-09  1:00           ` Mark Mitchell
@ 2008-04-09 10:55             ` Paolo Bonzini
  2008-04-14 16:02               ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-09 10:55 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Richard Guenther, Eric Botcazou, gcc-patches

Mark Mitchell wrote:
> Richard Guenther wrote:
> 
>> Not really, but maybe the FEs depend on things like
>>
>> const int i = 5;
>> &a[i]
>>
>> being an invariant address?
> 
> It's good to check that things work OK with -O0, but I think that if the 
> FEs depend on this, that's broken.  TREE_INVARIANT is about what GCC can 
> prove; not what any language standard says.  I think the FEs should be 
> using language-specific flags that correspond to language-specific 
> concepts (like C++'s "integral constant expressions").

Is this	an approval? :-)  (The patch obviously needs a GWP).

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-09 10:55             ` Paolo Bonzini
@ 2008-04-14 16:02               ` Paolo Bonzini
  2008-04-14 17:33                 ` Mark Mitchell
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-14 16:02 UTC (permalink / raw)
  Cc: Mark Mitchell, Richard Guenther, Eric Botcazou, gcc-patches


>> It's good to check that things work OK with -O0, but I think that if 
>> the FEs depend on this, that's broken.  TREE_INVARIANT is about what 
>> GCC can prove; not what any language standard says.  I think the FEs 
>> should be using language-specific flags that correspond to 
>> language-specific concepts (like C++'s "integral constant expressions").
> 
> Is this an approval? :-)  (The patch obviously needs a GWP).

PING.

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-14 16:02               ` Paolo Bonzini
@ 2008-04-14 17:33                 ` Mark Mitchell
  2008-04-21  6:19                   ` Mark Mitchell
  0 siblings, 1 reply; 14+ messages in thread
From: Mark Mitchell @ 2008-04-14 17:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Richard Guenther, Eric Botcazou, gcc-patches


>> Is this an approval? :-)  (The patch obviously needs a GWP).
> 
> PING.

I will review this this week.

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-14 17:33                 ` Mark Mitchell
@ 2008-04-21  6:19                   ` Mark Mitchell
  2008-04-21  7:38                     ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Mark Mitchell @ 2008-04-21  6:19 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Richard Guenther, Eric Botcazou, gcc-patches

Mark Mitchell wrote:

>>> Is this an approval? :-)  (The patch obviously needs a GWP).

> I will review this this week.

I've looked at this patch in detail now.  I like the core idea. 
Eliminating bits that we have to remember to maintain all over the 
compiler is a good idea.

However, I have two questions:

1. Are you sure that gimplify_init_ctor_preeval is never going to be 
called with an expression that would have been TREE_INVARIANT, but is 
not TREE_CONSTANT?  If that can ever happen, then we'll now take a 
different code path through that function, and I don't see how that's 
desirable.  But, maybe it is?

2. Did you consider simply replacing the definition of TREE_INVARIANT 
with "TREE_CONSTANT (NODE) || TREE_CODE (NODE) == SAVE_EXPR"?  That 
would still eliminate all of the places where we manually set 
TREE_INVARIANT, but still keep the mnemonic aspect of the current code. 
   It doesn't seem like a win to replicate out "TREE_CONSTANT (x) || 
TREE_CODE (x) == SAVE_EXPR" in several places when there's a concept 
that captures that well.  The idea of an expression being "constant 
within any given invocation of a function" seems useful so long as we 
have SAVE_EXPR.

I think that a patch that does as suggested by (2) would be slightly 
better than yours.  What do you think?

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Eliminate TREE_INVARIANT
  2008-04-21  6:19                   ` Mark Mitchell
@ 2008-04-21  7:38                     ` Paolo Bonzini
  0 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2008-04-21  7:38 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Richard Guenther, Eric Botcazou, gcc-patches


> 2. Did you consider simply replacing the definition of TREE_INVARIANT 
> with "TREE_CONSTANT (NODE) || TREE_CODE (NODE) == SAVE_EXPR"?
> 
> I think that a patch that does as suggested by (2) would be slightly 
> better than yours.  What do you think?

I agree, thanks!

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-04-21  5:12 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-05  7:36 [PATCH] Eliminate TREE_INVARIANT Paolo Bonzini
2008-04-05  7:40 ` Eric Botcazou
2008-04-05  7:58   ` Paolo Bonzini
2008-04-05 12:39     ` Richard Guenther
2008-04-05 12:41       ` Paolo Bonzini
2008-04-05 12:46         ` Richard Guenther
2008-04-05 14:35           ` Paolo Bonzini
2008-04-09  1:00           ` Mark Mitchell
2008-04-09 10:55             ` Paolo Bonzini
2008-04-14 16:02               ` Paolo Bonzini
2008-04-14 17:33                 ` Mark Mitchell
2008-04-21  6:19                   ` Mark Mitchell
2008-04-21  7:38                     ` Paolo Bonzini
2008-04-07 12:40       ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).