aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2008-04-23 15:00:52 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2008-04-23 15:00:52 +0000
commit51eed2800da645f00fb35fcee7a217090ec61f54 (patch)
tree576c9b8b70b89942ab3e7e3c2ebe4abeb33d66ea /gcc/tree.c
parent17d2c090a10e1ff15d78e4e139f7df7c39a54d4e (diff)
downloadgcc-51eed2800da645f00fb35fcee7a217090ec61f54.zip
gcc-51eed2800da645f00fb35fcee7a217090ec61f54.tar.gz
gcc-51eed2800da645f00fb35fcee7a217090ec61f54.tar.bz2
tree-cfg.c (verify_expr): Check with is_gimple_address.
2008-04-23 Paolo Bonzini <bonzini@gnu.org> * tree-cfg.c (verify_expr): Check with is_gimple_address. Don't check TREE_INVARIANT. * tree-gimple.c (is_gimple_address): New. (is_gimple_invariant_address): Simplify using decl_address_invariant_p. * tree-gimple.h (is_gimple_address): New. * tree.h (decl_address_invariant_p): New. * tree.c (make_node_stat): Don't set TREE_INVARIANT. (build_string): Likewise. (decl_address_invariant_p): New, from is_gimple_invariant_address. (tree_invariant_p_1): Likewise. (save_expr): Use it. (tree_invariant_p): New. (skip_simple_arithmetic): Use it. (stabilize_reference_1): Use it. (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-23 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-23 Paolo Bonzini <bonzini@gnu.org> * objc-act.c (objc_build_string_object): Don't set TREE_INVARIANT. cp: 2008-04-23 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-23 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-23 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. From-SVN: r134599
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c191
1 files changed, 135 insertions, 56 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 2a6ebb0..73adaa1 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -621,7 +621,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
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';
@@ -2056,7 +2054,111 @@ staticp (tree arg)
return NULL;
}
}
+
+
+
+/* Return whether OP is a DECL whose address is function-invariant. */
+
+bool
+decl_address_invariant_p (const_tree op)
+{
+ /* The conditions below are slightly less strict than the one in
+ staticp. */
+
+ 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;
+}
+
+
+/* Return true if T is function-invariant (internal function, does
+ not handle arithmetic; that's handled in skip_simple_arithmetic and
+ tree_invariant_p). */
+
+static bool tree_invariant_p (tree t);
+
+static bool
+tree_invariant_p_1 (tree t)
+{
+ tree op;
+
+ if (TREE_CONSTANT (t)
+ || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t)))
+ return true;
+
+ switch (TREE_CODE (t))
+ {
+ case SAVE_EXPR:
+ return true;
+
+ case ADDR_EXPR:
+ op = TREE_OPERAND (t, 0);
+ while (handled_component_p (op))
+ {
+ switch (TREE_CODE (op))
+ {
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ if (!tree_invariant_p (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);
+ }
+
+ return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/* Return true if T is function-invariant. */
+
+static bool
+tree_invariant_p (tree t)
+{
+ tree inner = skip_simple_arithmetic (t);
+ return tree_invariant_p_1 (inner);
+}
+
/* 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.
@@ -2091,11 +2193,10 @@ save_expr (tree expr)
Since it is no problem to reevaluate literals, we just return the
literal node. */
inner = skip_simple_arithmetic (t);
+ if (TREE_CODE (inner) == ERROR_MARK)
+ return inner;
- if (TREE_INVARIANT (inner)
- || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
- || TREE_CODE (inner) == SAVE_EXPR
- || TREE_CODE (inner) == ERROR_MARK)
+ if (tree_invariant_p_1 (inner))
return t;
/* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
@@ -2116,7 +2217,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 +2244,9 @@ 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_invariant_p (TREE_OPERAND (inner, 1)))
inner = TREE_OPERAND (inner, 0);
- else if (TREE_INVARIANT (TREE_OPERAND (inner, 0)))
+ else if (tree_invariant_p (TREE_OPERAND (inner, 0)))
inner = TREE_OPERAND (inner, 1);
else
break;
@@ -2815,7 +2915,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_invariant_p (e))
return e;
switch (TREE_CODE_CLASS (code))
@@ -2868,7 +2968,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 +2975,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 +2991,8 @@ recompute_tree_invariant_for_addr_expr (tree t)
??? 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 +3006,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 +3019,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 +3144,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
&& 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 +3164,13 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
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 +3207,12 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
|| 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 +3241,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 +3277,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 +3304,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 +3333,7 @@ build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
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 +3963,7 @@ merge_dllimport_decl_attributes (tree old, tree new)
"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))