[lto] Re-implement pass_ipa_free_lang_specifics [1/3]
Diego Novillo
dnovillo@google.com
Mon Jan 26 19:42:00 GMT 2009
This is the final patch I committed. I had held on to it because
it was showing 10 failures while building internal code. I had
inadvertently switched two arguments in one of the calls to
walk_tree in find_decls_types_r.
Diego.
* tree.h (TYPE_MAXVAL): Define.
(TYPE_MINVAL): Define.
* tree.c: Include cgraph.h, timevar.h and except.h.
(free_lang_data_in_type): Rename from reset_type_lang_specific.
Change argument to be the type to process.
Change return type to void.
Update all users.
(set_asm_name): Remove. Update all users.
(free_lang_data_in_decl): Rename from
reset_decl_lang_specific.
Change argument to be the decl to process.
Change return type to void.
Update all users.
Also analyze DECL_SIZE in RESULT_DECLs.
(struct free_lang_data_d): Declare.
(find_decls_types_r): New.
(get_eh_types_for_runtime): Move from lto-function-out.c.
(find_decls_types_in_eh_region): New.
(find_decls_types_in_node): New.
(find_decls_types_in_var): New.
(free_lang_data_in_cgraph): New.
(free_lang_data): Rename from free_lang_specifics
Call free_lang_data_in_cgraph.
Set char_type_node to unsigned_char_type_node if -funsigned-char
was given.
(gate_free_lang_data): Rename from gate_free_lang_specifics.
Update all users.
(pass_ipa_free_lang_data): Rename from free_lang_specifics.
Update all users.
Add timer TV_IPA_FREE_LANG_DATA.
* Makefile.in (tree.o): Add dependency on CGRAPH_H,
TIMEVAR_H and except.h.
* lto-function-out.c (get_eh_types_for_runtime): Move to tree.c.
(output_eh_region): Do not call get_eh_types_for_runtime.
* timevar.def (TV_IPA_FREE_LANG_DATA): Define.
* langhooks.h (struct lang_hooks): Rename
free_lang_specifics to free_lang_data.
Update all users.
* langhooks-def.h (LANG_HOOKS_FREE_LANG_DATA): Rename
from LANG_HOOKS_RESET_LANG_SPECIFICS. Update all users.
* except.c (output_ttype): Only call lookup_type_for_runtime
if TYPE is actually a type.
* tree.c (uid2type_map): Remove. Update all users.
(decl_for_uid_map): Remove. Update all users.
(insert_decl_to_uid_decl_map): Remove. Update all users.
(insert_type_to_uid_type_map): Remove. Update all users.
(uid_type_map_eq): Remove. Update all users.
(uid_type_map_hash): Remove. Update all users.
(insert_decl_to_uid_decl_map): Remove. Update all users.
(remove_decl_from_map): Remove. Update all users.
* tree.c (free_lang_data): Set lang_hooks.types_compatible_p
to gimple_types_compatible_p.
* gimple.c (gimple_types_compatible_p): Moved from
lto/lto-lang.c. Renamed from lto_types_compatible_p.
* gimple.h (gimple_types_compatible_p): Declare.
cp/ChangeLog.lto
2009-01-26 Diego Novillo <dnovillo@google.com>
* tree.c (cp_free_lang_data): Rename from cp_reset_lang_specifics.
Update all users.
lto/ChangeLog
* lto-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Update.
* lto-lang.c (lto_types_compatible_p): Move to gimple.c
and rename into gimple_types_compatible_p.
Index: tree.c
===================================================================
--- tree.c (revision 143674)
+++ tree.c (revision 143675)
@@ -54,6 +54,9 @@ along with GCC; see the file COPYING3.
#include "tree-pass.h"
#include "langhooks-def.h"
#include "diagnostic.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "except.h"
/* Tree code classes. */
@@ -148,15 +151,6 @@ static GTY(()) int next_decl_uid;
/* Unique id for next type created. */
static GTY(()) int next_type_uid = 1;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t uid2type_map;
-
-/* Mapping from unique DECL_UID to the decl tree node. */
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t decl_for_uid_map;
-
-static void insert_decl_to_uid_decl_map (tree);
-
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
@@ -272,41 +266,6 @@ const char * const omp_clause_code_name[
/* Init tree.c. */
-/* Add tree NODE into the UID2TYPE_MAP hash table. */
-
-static void
-insert_type_to_uid_type_map (tree node)
-{
- void **slot;
- struct tree_type key;
-
- key.uid = TYPE_UID (node);
- slot = htab_find_slot_with_hash (uid2type_map,
- &key, TYPE_UID (node), INSERT);
-
- gcc_assert (!*slot);
-
- *(tree *)slot = node;
-}
-
-/* Compares tree VA and tree VB. */
-
-static int
-uid_type_map_eq (const void *va, const void *vb)
-{
- const_tree a = (const_tree) va;
- const_tree b = (const_tree) vb;
- return (a->type.uid == b->type.uid);
-}
-
-/* Hash the tree ITEM. */
-
-static unsigned int
-uid_type_map_hash (const void *item)
-{
- return ((const_tree)item)->type.uid;
-}
-
void
init_ttree (void)
{
@@ -329,12 +288,6 @@ init_ttree (void)
int_cst_node = make_node (INTEGER_CST);
- decl_for_uid_map = htab_create_ggc (4093, uid_decl_map_hash,
- uid_decl_map_eq, NULL);
-
- uid2type_map = htab_create_ggc (4093, uid_type_map_hash,
- uid_type_map_eq, NULL);
-
cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
cl_option_hash_eq, NULL);
@@ -736,8 +689,6 @@ make_node_stat (enum tree_code code MEM_
}
DECL_SOURCE_LOCATION (t) = input_location;
DECL_UID (t) = next_decl_uid++;
- insert_decl_to_uid_decl_map (t);
-
break;
case tcc_type:
@@ -753,7 +704,6 @@ make_node_stat (enum tree_code code MEM_
/* We have not yet computed the alias set for this type. */
TYPE_ALIAS_SET (t) = -1;
- insert_type_to_uid_type_map (t);
break;
case tcc_constant:
@@ -828,7 +778,6 @@ copy_node_stat (tree node MEM_STAT_DECL)
SET_DECL_RESTRICT_BASE (t, DECL_GET_RESTRICT_BASE (node));
DECL_BASED_ON_RESTRICT_P (t) = 1;
}
- insert_decl_to_uid_decl_map (t);
}
else if (TREE_CODE_CLASS (code) == tcc_type)
{
@@ -847,7 +796,6 @@ copy_node_stat (tree node MEM_STAT_DECL)
TYPE_CACHED_VALUES_P (t) = 0;
TYPE_CACHED_VALUES (t) = NULL_TREE;
}
- insert_type_to_uid_type_map (t);
}
return t;
@@ -3560,45 +3508,6 @@ build_nt_call_list (tree fn, tree arglis
return t;
}
-/* Insert the declaration NODE into the map mapping its unique uid
- back to the tree. */
-
-static void
-insert_decl_to_uid_decl_map (tree node)
-{
- void **slot;
- struct tree_decl_minimal key;
-
- key.uid = DECL_UID (node);
- slot = htab_find_slot_with_hash (decl_for_uid_map,
- &key, DECL_UID (node), INSERT);
-
- /* We should never try to re-insert a decl with the same uid.
- ??? The C++ frontend breaks this invariant. Hopefully in a
- non-fatal way, so just overwrite the slot in this case. */
-#if 0
- gcc_assert (!*slot);
-#endif
-
- *(tree *)slot = node;
-}
-
-/* Remove the declaration tree DECL from the global UID to decl map.
- This needs to be called if you ggc_free a decl tree, otherwise
- garbage collection will take care of it. */
-
-void
-remove_decl_from_map (tree decl)
-{
- struct tree_decl_minimal key;
-
- key.uid = DECL_UID (decl);
-#if ENABLE_CHECKING
- gcc_assert (decl == htab_find_with_hash (decl_for_uid_map, &key, key.uid));
-#endif
- htab_remove_elt_with_hash (decl_for_uid_map, &key, key.uid);
-}
-
/* Create a DECL_... node of code CODE, name NAME and data type TYPE.
We do NOT enter this node in any sort of symbol table.
@@ -3884,13 +3793,15 @@ build_type_attribute_variant (tree ttype
TYPE_QUALS (ttype));
}
-/* Helper function of free_lang_specifics. */
+/* Reset all language specific information still present in TYPE. */
-static int
-reset_type_lang_specific (void **slot, void *unused ATTRIBUTE_UNUSED)
+static void
+free_lang_data_in_type (tree type)
{
- tree type = *(tree *) slot;
- lang_hooks.reset_lang_specifics (type);
+ gcc_assert (TYPE_P (type));
+
+ /* Give the FE a chance to remove its own data first. */
+ lang_hooks.free_lang_data (type);
TREE_LANG_FLAG_0 (type) = 0;
TREE_LANG_FLAG_1 (type) = 0;
@@ -3981,12 +3892,9 @@ reset_type_lang_specific (void **slot, v
scoping and should not be part of the IR.
FIXME lto: This will break debug info generation. */
TYPE_CONTEXT (type) = NULL_TREE;
-
- return 1;
}
-
/* Return true if DECL may need an assembler name to be set. */
static inline bool
@@ -4021,29 +3929,16 @@ need_assembler_name_p (tree decl)
}
-/* Helper function of free_lang_specifics.
- Set the assembler name for nodes that may need one. */
-
-static int
-set_asm_name (void **slot, void *unused ATTRIBUTE_UNUSED)
-{
- tree decl = *((tree *) slot);
-
- if (need_assembler_name_p (decl))
- lang_hooks.set_decl_assembler_name (decl);
-
- return 1;
-}
-
-
-/* Helper function of free_lang_specifics. */
+/* Reset all language specific information still present in symbol
+ DECL. */
-static int
-reset_decl_lang_specific (void **slot, void *unused ATTRIBUTE_UNUSED)
+static void
+free_lang_data_in_decl (tree decl)
{
- tree decl = *(tree *) slot;
+ gcc_assert (DECL_P (decl));
- lang_hooks.reset_lang_specifics (decl);
+ /* Give the FE a chance to remove its own data first. */
+ lang_hooks.free_lang_data (decl);
TREE_LANG_FLAG_0 (decl) = 0;
TREE_LANG_FLAG_1 (decl) = 0;
@@ -4056,9 +3951,9 @@ reset_decl_lang_specific (void **slot, v
if (TREE_CODE (decl) == CONST_DECL)
DECL_CONTEXT (decl) = NULL_TREE;
+ /* Ignore any intervening types, because we are going to clear their
+ TYPE_CONTEXT fields. */
if (TREE_CODE (decl) != FIELD_DECL)
- /* Ignore any intervening types, because we
- are going to clear their TYPE_CONTEXT fields. */
DECL_CONTEXT (decl) = decl_function_context (decl);
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
@@ -4078,7 +3973,9 @@ reset_decl_lang_specific (void **slot, v
}
}
- if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == FIELD_DECL)
+ if (TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == FIELD_DECL
+ || TREE_CODE (decl) == RESULT_DECL)
{
tree unit_size = DECL_SIZE_UNIT (decl);
tree size = DECL_SIZE (decl);
@@ -4123,30 +4020,315 @@ reset_decl_lang_specific (void **slot, v
in cgraph_node. */
DECL_CONTEXT (decl) = NULL_TREE;
}
+}
- return 1;
+/* Data used when collecting DECLs and TYPEs for language data removal. */
+
+struct free_lang_data_d
+{
+ /* Set of traversed objects. Used to avoid duplicate visits. */
+ struct pointer_set_t *pset;
+
+ /* Array of symbols to process with free_lang_data_in_decl. */
+ VEC(tree,heap) *decls;
+
+ /* Array of types to process with free_lang_data_in_type. */
+ VEC(tree,heap) *types;
+};
+
+
+/* Operand callback helper for free_lang_data_in_node. *TP is the
+ subtree operand being considered. */
+
+static tree
+find_decls_types_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
+{
+ tree t = *tp;
+ struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
+
+ if (DECL_P (t))
+ {
+ /* Note that walk_tree does not traverse every possible field in
+ decls, so we have to do our own traversals here. */
+ VEC_safe_push (tree, heap, fld->decls, t);
+
+ walk_tree (&DECL_NAME (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_CONTEXT (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_SIZE (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_INITIAL (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_ABSTRACT_ORIGIN (t), find_decls_types_r, fld,
fld->pset);
+
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ {
+ walk_tree (&DECL_ARGUMENTS (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_RESULT (t), find_decls_types_r, fld, fld->pset);
+ }
+ else if (TREE_CODE (t) == TYPE_DECL)
+ {
+ walk_tree (&DECL_ARGUMENT_FLD (t), find_decls_types_r, fld,
+ fld->pset);
+ walk_tree (&DECL_VINDEX (t), find_decls_types_r, fld, fld->pset);
+ }
+ else if (TREE_CODE (t) == FIELD_DECL)
+ {
+ walk_tree (&DECL_FIELD_OFFSET (t), find_decls_types_r, fld,
+ fld->pset);
+ walk_tree (&DECL_BIT_FIELD_TYPE (t), find_decls_types_r, fld,
+ fld->pset);
+ walk_tree (&DECL_QUALIFIER (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&DECL_FIELD_BIT_OFFSET (t), find_decls_types_r, fld,
+ fld->pset);
+ walk_tree (&DECL_FCONTEXT (t), find_decls_types_r, fld, fld->pset);
+ }
+ else if (TREE_CODE (t) == VAR_DECL)
+ {
+ walk_tree (&DECL_SECTION_NAME (t), find_decls_types_r, fld,
+ fld->pset);
+ walk_tree (&DECL_COMDAT_GROUP (t), find_decls_types_r, fld,
+ fld->pset);
+ }
+ }
+ else if (TYPE_P (t))
+ {
+ /* Note that walk_tree does not traverse every possible field in
+ types, so we have to do our own traversals here. */
+ VEC_safe_push (tree, heap, fld->types, t);
+
+ walk_tree (&TYPE_CACHED_VALUES (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_SIZE (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_POINTER_TO (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_REFERENCE_TO (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_NAME (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_MINVAL (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_MAXVAL (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_NEXT_VARIANT (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_MAIN_VARIANT (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_CONTEXT (t), find_decls_types_r, fld, fld->pset);
+ walk_tree (&TYPE_CANONICAL (t), find_decls_types_r, fld, fld->pset);
+ }
+
+ if (TREE_TYPE (t))
+ walk_tree (&TREE_TYPE (t), find_decls_types_r, fld, fld->pset);
+
+ /* Do not recurse into TREE_CHAIN to avoid blowing up the stack. */
+ for (tp = &TREE_CHAIN (t); *tp; tp = &TREE_CHAIN (*tp))
+ {
+ tree saved_chain = TREE_CHAIN (*tp);
+ TREE_CHAIN (*tp) = NULL_TREE;
+ walk_tree (tp, find_decls_types_r, fld, fld->pset);
+ TREE_CHAIN (*tp) = saved_chain;
+ }
+
+ return NULL_TREE;
}
-/* Free resources that are used by FE but are not needed once they are done. */
-static unsigned
-free_lang_specifics (void)
+/* Translate all the types in LIST with the corresponding runtime
+ types. */
+
+static tree
+get_eh_types_for_runtime (tree list)
{
- struct cgraph_node *node;
+ tree head, prev;
- /* Set assembler names now, as callbacks from the back-end
- will fail after we strip DECL_CONTEXT from declaration nodes. */
- htab_traverse (decl_for_uid_map, set_asm_name, NULL);
+ if (list == NULL_TREE)
+ return NULL_TREE;
- for (node = cgraph_nodes; node; node = node->next)
+ head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+ prev = head;
+ list = TREE_CHAIN (list);
+ while (list)
{
- tree decl = node->decl;
- if (!DECL_ASSEMBLER_NAME_SET_P (decl))
- lang_hooks.set_decl_assembler_name (decl);
+ tree n = build_tree_list (0, lookup_type_for_runtime
(TREE_VALUE (list)));
+ TREE_CHAIN (prev) = n;
+ prev = TREE_CHAIN (prev);
+ list = TREE_CHAIN (list);
}
- htab_traverse (decl_for_uid_map, reset_decl_lang_specific, NULL);
- htab_traverse (uid2type_map, reset_type_lang_specific, NULL);
+ return head;
+}
+
+
+/* Find decls and types referenced in EH region R and store them in
+ FLD->DECLS and FLD->TYPES. */
+
+static void
+find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
+{
+ if (r == NULL)
+ return;
+
+ /* The types referenced in R must first be changed to the EH types
+ used at runtime. This removes references to FE types in the
+ region. */
+ if (r->type == ERT_CATCH)
+ {
+ tree list = r->u.eh_catch.type_list;
+ r->u.eh_catch.type_list = get_eh_types_for_runtime (list);
+ walk_tree (&r->u.eh_catch.type_list, find_decls_types_r, fld, fld->pset);
+ }
+ else if (r->type == ERT_ALLOWED_EXCEPTIONS)
+ {
+ tree list = r->u.allowed.type_list;
+ r->u.allowed.type_list = get_eh_types_for_runtime (list);
+ walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
+ }
+}
+
+
+/* Find decls and types referenced in cgraph node N and store them in
+ FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
+ look for *every* kind of DECL and TYPE node reachable from N,
+ including those embedded inside types and decls (i.e,, TYPE_DECLs,
+ NAMESPACE_DECLs, etc). */
+
+static void
+find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
+{
+ basic_block bb;
+ struct function *fn;
+
+ /* Although free_lang_data_in_cgraph will set the assembler name on
+ most DECLs, it refuses to do it on unused ones. For cgraph
+ nodes, we need to set it even if it's seemingly unused. */
+ if (!DECL_ASSEMBLER_NAME_SET_P (n->decl))
+ lang_hooks.set_decl_assembler_name (n->decl);
+
+ walk_tree (&n->decl, find_decls_types_r, fld, fld->pset);
+
+ if (!gimple_has_body_p (n->decl))
+ return;
+
+ gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+ fn = DECL_STRUCT_FUNCTION (n->decl);
+
+ /* Traverse EH regions in FN. */
+ if (fn->eh->region_array)
+ {
+ unsigned i;
+ eh_region r;
+
+ for (i = 0; VEC_iterate (eh_region, fn->eh->region_array, i, r); i++)
+ find_decls_types_in_eh_region (r, fld);
+ }
+
+ /* Traverse every statement in FN. */
+ FOR_EACH_BB_FN (bb, fn)
+ {
+ gimple_stmt_iterator si;
+ unsigned i;
+
+ for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple phi = gsi_stmt (si);
+
+ for (i = 0; i < gimple_phi_num_args (phi); i++)
+ {
+ tree *arg_p = gimple_phi_arg_def_ptr (phi, i);
+ walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
+ }
+ }
+
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple stmt = gsi_stmt (si);
+
+ for (i = 0; i < gimple_num_ops (stmt); i++)
+ {
+ tree *arg_p = gimple_op_ptr (stmt, i);
+ walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
+ }
+ }
+ }
+}
+
+
+/* Find decls and types referenced in varpool node N and store them in
+ FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
+ look for *every* kind of DECL and TYPE node reachable from N,
+ including those embedded inside types and decls (i.e,, TYPE_DECLs,
+ NAMESPACE_DECLs, etc). */
+
+static void
+find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
+{
+ walk_tree (&v->decl, find_decls_types_r, fld, fld->pset);
+}
+
+
+/* Free language specific information for every operand and expression
+ in every node of the call graph. This process operates in three stages:
+
+ 1- Every callgraph node and varpool node is traversed looking for
+ decls and types embedded in them. This is a more exhaustive
+ search than that done by find_referenced_vars, because it will
+ also collect individual fields, decls embedded in types, etc.
+
+ 2- All the decls found are sent to free_lang_data_in_decl.
+
+ 3- All the types found are sent to free_lang_data_in_type.
+
+ The ordering between decls and types is important because
+ free_lang_data_in_decl sets assembler names, which includes
+ mangling. So types cannot be freed up until assembler names have
+ been set up. */
+
+static void
+free_lang_data_in_cgraph (void)
+{
+ struct cgraph_node *n;
+ struct varpool_node *v;
+ struct free_lang_data_d fld;
+ tree t;
+ unsigned i;
+
+ /* Initialize sets and arrays to store referenced decls and types. */
+ fld.pset = pointer_set_create ();
+ fld.decls = VEC_alloc (tree, heap, 100);
+ fld.types = VEC_alloc (tree, heap, 100);
+
+ /* Find decls and types in the body of every function in the callgraph. */
+ for (n = cgraph_nodes; n; n = n->next)
+ find_decls_types_in_node (n, &fld);
+
+ /* Find decls and types in every varpool symbol. */
+ for (v = varpool_nodes_queue; v; v = v->next_needed)
+ find_decls_types_in_var (v, &fld);
+
+ /* Set the assembler name on every decl found. We need to do this
+ now because free_lang_data_in_decl will invalidate data needed
+ for mangling. This breaks mangling on interdependent decls. */
+ for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+ if (need_assembler_name_p (t))
+ lang_hooks.set_decl_assembler_name (t);
+
+ /* Traverse every decl found freeing its language data. */
+ for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+ free_lang_data_in_decl (t);
+
+ /* Traverse every type found freeing its language data. */
+ for (i = 0; VEC_iterate (tree, fld.types, i, t); i++)
+ free_lang_data_in_type (t);
+
+ pointer_set_destroy (fld.pset);
+ VEC_free (tree, heap, fld.decls);
+ VEC_free (tree, heap, fld.types);
+}
+
+
+/* Free resources that are used by FE but are not needed once they are done. */
+
+static unsigned
+free_lang_data (void)
+{
+ /* Traverse the IL resetting language specific information for
+ operands, expressions, etc. */
+ free_lang_data_in_cgraph ();
/* FIXME lto. This is a hack. ptrdiff_type_node is only created
by the C/C++ FE. This should be converted to some similar
@@ -4157,10 +4339,11 @@ free_lang_specifics (void)
a variant copy of ptr_type_node for front-end purposes. */
fileptr_type_node = ptr_type_node;
- /* Reset some langhooks. */
+ /* Reset some langhooks. */
lang_hooks.callgraph.analyze_expr = NULL;
+ lang_hooks.types_compatible_p = gimple_types_compatible_p;
- /* FIXME lto: We have to compute these names early. */
+ /* FIXME lto: We have to compute these names early. */
lang_hooks.dwarf_name = lhd_dwarf_name;
lang_hooks.decl_printable_name = lhd_decl_printable_name;
@@ -4179,29 +4362,29 @@ free_lang_specifics (void)
}
-/* Gate function for free_lang_specifics. FIXME lto. This should be
+/* Gate function for free_lang_data. FIXME lto. This should be
unconditional and not depend on whether we're producing LTO
information and it should be done very early on. This currently
breaks libstdc++ builds, though. */
static bool
-gate_free_lang_specifics (void)
+gate_free_lang_data (void)
{
return flag_generate_lto;
}
-struct simple_ipa_opt_pass pass_ipa_free_lang_specifics =
+struct simple_ipa_opt_pass pass_ipa_free_lang_data =
{
{
SIMPLE_IPA_PASS,
NULL, /* name */
- gate_free_lang_specifics, /* gate */
- free_lang_specifics, /* execute */
+ gate_free_lang_data, /* gate */
+ free_lang_data, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_IPA_FREE_LANG_DATA, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
Index: tree.h
===================================================================
--- tree.h (revision 143674)
+++ tree.h (revision 143675)
@@ -2098,6 +2098,8 @@ struct tree_block GTY(())
#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type.next_variant)
#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context)
+#define TYPE_MAXVAL(NODE) (TYPE_CHECK (NODE)->type.maxval)
+#define TYPE_MINVAL(NODE) (TYPE_CHECK (NODE)->type.minval)
/* Vector types need to check target flags to determine type. */
extern enum machine_mode vector_type_mode (const_tree);
@@ -5255,10 +5257,6 @@ struct tree_int_map GTY(())
#define tree_int_map_hash tree_map_base_hash
#define tree_int_map_marked_p tree_map_base_marked_p
-/* Map from a DECL_UID to the decl tree. */
-
-extern void remove_decl_from_map (tree);
-
/* Map from a tree to initialization/finalization priorities. */
struct tree_priority_map GTY(())
Index: tree-pass.h
===================================================================
--- tree-pass.h (revision 143674)
+++ tree-pass.h (revision 143675)
@@ -391,7 +391,7 @@ extern struct gimple_opt_pass pass_build
extern struct gimple_opt_pass pass_reset_cc_flags;
/* IPA Passes */
-extern struct simple_ipa_opt_pass pass_ipa_free_lang_specifics;
+extern struct simple_ipa_opt_pass pass_ipa_free_lang_data;
extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
extern struct simple_ipa_opt_pass pass_ipa_early_inline;
Index: lto-function-out.c
===================================================================
--- lto-function-out.c (revision 143674)
+++ lto-function-out.c (revision 143675)
@@ -675,32 +675,6 @@ output_record_start (struct output_block
}
-/* Translate all the types in LIST with the corresponding runtime
- types. */
-
-static tree
-get_eh_types_for_runtime (tree list)
-{
- tree head, prev;
-
- if (list == NULL_TREE)
- return NULL_TREE;
-
- head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
- prev = head;
- list = TREE_CHAIN (list);
- while (list)
- {
- tree n = build_tree_list (0, lookup_type_for_runtime
(TREE_VALUE (list)));
- TREE_CHAIN (prev) = n;
- prev = TREE_CHAIN (prev);
- list = TREE_CHAIN (list);
- }
-
- return head;
-}
-
-
/* Output EH region R to OB. */
static void
@@ -790,10 +764,7 @@ output_eh_region (struct output_block *o
by calling output_zero. */
list = r->u.eh_catch.type_list;
if (list)
- {
- list = get_eh_types_for_runtime (list);
- output_expr_operand (ob, list);
- }
+ output_expr_operand (ob, list);
else
output_zero (ob);
@@ -805,7 +776,7 @@ output_eh_region (struct output_block *o
}
else if (r->type == ERT_ALLOWED_EXCEPTIONS)
{
- tree list = get_eh_types_for_runtime (r->u.allowed.type_list);
+ tree list = r->u.allowed.type_list;
if (list)
output_expr_operand (ob, list);
else
@@ -2750,7 +2721,7 @@ output_type_decl (struct output_block *o
/* Must output name before type. */
output_tree (ob, decl->decl_minimal.name);
- /* Should be cleared by pass_ipa_free_lang_specifics. */
+ /* Should be cleared by pass_ipa_free_lang_data. */
gcc_assert (decl->decl_minimal.context == NULL_TREE);
output_tree (ob, decl->decl_with_vis.assembler_name);
@@ -2767,7 +2738,7 @@ output_type_decl (struct output_block *o
output_tree (ob, decl->decl_common.size);
output_tree (ob, decl->decl_common.size_unit);
- /* We expect pass_ipa_free_lang_specifics to clear the INITIAL field. */
+ /* We expect pass_ipa_free_lang_data to clear the INITIAL field. */
gcc_assert (decl->decl_common.initial == NULL_TREE);
/* lang_specific */
@@ -2912,7 +2883,7 @@ output_type (struct output_block *ob, tr
LTO_DEBUG_TOKEN ("binfo");
output_tree (ob, type->type.binfo);
- /* Should be cleared by pass_ipa_free_lang_specifics. */
+ /* Should be cleared by pass_ipa_free_lang_data. */
gcc_assert (type->type.context == NULL_TREE);
LTO_DEBUG_TOKEN ("canonical");
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 143674)
+++ cp/decl.c (revision 143675)
@@ -2156,7 +2156,6 @@ duplicate_decls (tree newdecl, tree oldd
/* The NEWDECL will no longer be needed. Because every out-of-class
declaration of a member results in a call to duplicate_decls,
freeing these nodes represents in a significant savings. */
- remove_decl_from_map (newdecl);
ggc_free (newdecl);
return olddecl;
Index: cp/cp-objcp-common.h
===================================================================
--- cp/cp-objcp-common.h (revision 143674)
+++ cp/cp-objcp-common.h (revision 143675)
@@ -30,8 +30,8 @@ extern tree objcp_tsubst_copy_and_build
specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
respectively. */
-#undef LANG_HOOKS_RESET_LANG_SPECIFICS
-#define LANG_HOOKS_RESET_LANG_SPECIFICS cp_reset_lang_specifics
+#undef LANG_HOOKS_FREE_LANG_DATA
+#define LANG_HOOKS_FREE_LANG_DATA cp_free_lang_data
#undef LANG_HOOKS_TREE_SIZE
#define LANG_HOOKS_TREE_SIZE cp_tree_size
#undef LANG_HOOKS_FINISH
Index: cp/tree.c
===================================================================
--- cp/tree.c (revision 143674)
+++ cp/tree.c (revision 143675)
@@ -2829,7 +2829,7 @@ cp_fix_function_decl_p (tree decl)
/* Clean the C++ specific parts of the tree T. */
void
-cp_reset_lang_specifics (tree t)
+cp_free_lang_data (tree t)
{
if (TREE_CODE (t) == METHOD_TYPE
|| TREE_CODE (t) == FUNCTION_TYPE)
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 143674)
+++ cp/cp-tree.h (revision 143675)
@@ -4819,7 +4819,7 @@ extern tree finish_decltype_type
extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
/* in tree.c */
-void cp_reset_lang_specifics (tree t);
+void cp_free_lang_data (tree t);
extern void lang_check_failed (const char *, int,
const char *) ATTRIBUTE_NORETURN;
extern tree stabilize_expr (tree, tree *);
Index: timevar.def
===================================================================
--- timevar.def (revision 143674)
+++ timevar.def (revision 143675)
@@ -53,6 +53,7 @@ DEFTIMEVAR (TV_IPA_REFERENCE , "
DEFTIMEVAR (TV_IPA_PURE_CONST , "ipa pure const")
DEFTIMEVAR (TV_IPA_TYPE_ESCAPE , "ipa type escape")
DEFTIMEVAR (TV_IPA_PTA , "ipa points-to")
+DEFTIMEVAR (TV_IPA_FREE_LANG_DATA , "ipa free lang data")
/* Time spent by constructing CFG. */
DEFTIMEVAR (TV_CFG , "cfg construction")
/* Time spent by cleaning up CFG. */
Index: langhooks.h
===================================================================
--- langhooks.h (revision 143674)
+++ langhooks.h (revision 143675)
@@ -240,7 +240,7 @@ struct lang_hooks
size_t identifier_size;
/* Remove any parts of the tree that are used only by the FE. */
- void (*reset_lang_specifics) (tree);
+ void (*free_lang_data) (tree);
/* Determines the size of any language-specific tcc_constant or
tcc_exceptional nodes. Since it is called from make_node, the
Index: except.c
===================================================================
--- except.c (revision 143674)
+++ except.c (revision 143675)
@@ -3481,7 +3481,14 @@ output_ttype (tree type, int tt_format,
{
struct varpool_node *node;
- type = lookup_type_for_runtime (type);
+ /* FIXME lto. During LTO compiles, pass_ipa_free_lang_data
+ changes all types to runtime types so TYPE should already be
+ a runtime type reference. When pass_ipa_free_lang data is
+ made a default pass, we can then remove the call to
+ lookup_type_for_runtime below. */
+ if (TYPE_P (type))
+ type = lookup_type_for_runtime (type);
+
value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
/* Let cgraph know that the rtti decl is used. Not all of the
Index: lto/lto.c
===================================================================
--- lto/lto.c (revision 143674)
+++ lto/lto.c (revision 143675)
@@ -1308,7 +1308,6 @@ free_decl (const void *p, void *data ATT
const_tree ct = (const_tree) p;
tree t = CONST_CAST_TREE (ct);
- remove_decl_from_map (t);
lto_symtab_clear_resolution (t);
ggc_free (t);
return true;
Index: lto/lto-lang.c
===================================================================
--- lto/lto-lang.c (revision 143674)
+++ lto/lto-lang.c (revision 143675)
@@ -906,30 +906,6 @@ lto_builtin_function (tree decl)
return decl;
}
-static int
-lto_types_compatible_p (tree type1, tree type2)
-{
- if (TREE_CODE (type1) == RECORD_TYPE
- && TREE_CODE (type2) == RECORD_TYPE)
- {
- /* Check structural equality. */
- tree f1, f2;
-
- for (f1 = TYPE_FIELDS (type1), f2 = TYPE_FIELDS (type2);
- f1 && f2;
- f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
- {
- if (TREE_CODE (f1) != TREE_CODE (f2)
- || DECL_NAME (f1) != DECL_NAME (f2))
- break;
- }
-
- return f1 && f2 ? 0 : 1;
- }
-
- return TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2);
-}
-
static void
lto_register_builtin_type (tree type, const char *name)
{
@@ -1074,7 +1050,7 @@ static void lto_init_ts (void)
#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
#undef LANG_HOOKS_TYPES_COMPATIBLE_P
-#define LANG_HOOKS_TYPES_COMPATIBLE_P lto_types_compatible_p
+#define LANG_HOOKS_TYPES_COMPATIBLE_P gimple_types_compatible_p
/* Attribute hooks. */
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
Index: Makefile.in
===================================================================
--- Makefile.in (revision 143674)
+++ Makefile.in (revision 143675)
@@ -2135,7 +2135,7 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H)
$(TOPLEV_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H)
langhooks.h \
$(REAL_H) gt-tree.h tree-iterator.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
$(OBSTACK_H) pointer-set.h fixed-value.h tree-pass.h langhooks-def.h \
- $(DIAGNOSTIC_H)
+ $(DIAGNOSTIC_H) $(CGRAPH_H) $(TIMEVAR_H) except.h
tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TOPLEV_H) $(SPLAY_TREE_H) $(TREE_DUMP_H) \
tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h
Index: gimple.c
===================================================================
--- gimple.c (revision 143674)
+++ gimple.c (revision 143675)
@@ -3192,4 +3192,31 @@ gimple_call_copy_skip_args (gimple stmt,
return new_stmt;
}
+
+/* Return 1 if TYPE1 and TYPE2 are structurally compatible and/or they
+ have the same main variant. */
+
+int
+gimple_types_compatible_p (tree type1, tree type2)
+{
+ if (TREE_CODE (type1) == RECORD_TYPE
+ && TREE_CODE (type2) == RECORD_TYPE)
+ {
+ /* Check structural equality. */
+ tree f1, f2;
+
+ for (f1 = TYPE_FIELDS (type1), f2 = TYPE_FIELDS (type2);
+ f1 && f2;
+ f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+ {
+ if (TREE_CODE (f1) != TREE_CODE (f2)
+ || DECL_NAME (f1) != DECL_NAME (f2))
+ break;
+ }
+
+ return f1 && f2 ? 0 : 1;
+ }
+
+ return TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2);
+}
#include "gt-gimple.h"
Index: gimple.h
===================================================================
--- gimple.h (revision 143674)
+++ gimple.h (revision 143675)
@@ -913,6 +913,7 @@ extern bool is_gimple_call_addr (tree);
extern tree get_call_expr_in (tree t);
extern void recalculate_side_effects (tree);
+extern int gimple_types_compatible_p (tree, tree);
/* In gimplify.c */
extern tree create_tmp_var_raw (tree, const char *);
Index: passes.c
===================================================================
--- passes.c (revision 143674)
+++ passes.c (revision 143675)
@@ -536,7 +536,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_inline_parameters);
NEXT_PASS (pass_rebuild_cgraph_edges);
}
- NEXT_PASS (pass_ipa_free_lang_specifics);
+ NEXT_PASS (pass_ipa_free_lang_data);
NEXT_PASS (pass_early_local_passes);
{
struct opt_pass **p = &pass_early_local_passes.pass.sub;
Index: lto-section-out.c
===================================================================
--- lto-section-out.c (revision 143674)
+++ lto-section-out.c (revision 143675)
@@ -867,8 +867,7 @@ lto_get_common_nodes (void)
distinction should only be relevant to the front-end, so we always
use the C definition here in lto1.
- These should be assured in pass_ipa_free_lang_specifics. */
-
+ These should be assured in pass_ipa_free_lang_data. */
gcc_assert (fileptr_type_node == ptr_type_node);
gcc_assert (TYPE_MAIN_VARIANT (fileptr_type_node) == ptr_type_node);
Index: langhooks-def.h
===================================================================
--- langhooks-def.h (revision 143674)
+++ langhooks-def.h (revision 143675)
@@ -103,7 +103,7 @@ extern void lhd_omp_firstprivatize_type_
#define LANG_HOOKS_DECL_PRINTABLE_NAME lhd_decl_printable_name
#define LANG_HOOKS_DWARF_NAME lhd_dwarf_name
#define LANG_HOOKS_EXPR_SIZE lhd_expr_size
-#define LANG_HOOKS_RESET_LANG_SPECIFICS lhd_do_nothing_t
+#define LANG_HOOKS_FREE_LANG_DATA lhd_do_nothing_t
#define LANG_HOOKS_TREE_SIZE lhd_tree_size
#define LANG_HOOKS_TYPES_COMPATIBLE_P lhd_types_compatible_p
#define LANG_HOOKS_BUILTIN_FUNCTION lhd_builtin_function
@@ -239,7 +239,7 @@ extern void lhd_end_section (void);
#define LANG_HOOKS_INITIALIZER { \
LANG_HOOKS_NAME, \
LANG_HOOKS_IDENTIFIER_SIZE, \
- LANG_HOOKS_RESET_LANG_SPECIFICS, \
+ LANG_HOOKS_FREE_LANG_DATA, \
LANG_HOOKS_TREE_SIZE, \
LANG_HOOKS_INIT_OPTIONS, \
LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
More information about the Gcc-patches
mailing list