diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 150 |
1 files changed, 150 insertions, 0 deletions
@@ -175,6 +175,16 @@ static GTY (()) tree int_cst_node; static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) htab_t int_cst_hash_table; +/* Hash table for optimization flags and target option flags. Use the same + hash table for both sets of options. Nodes for building the current + optimization and target option nodes. The assumption is most of the time + the options created will already be in the hash table, so we avoid + allocating and freeing up a node repeatably. */ +static GTY (()) tree cl_optimization_node; +static GTY (()) tree cl_target_option_node; +static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) + htab_t cl_option_hash_table; + /* General tree->tree mapping structure for use in hash tables. */ @@ -196,6 +206,8 @@ static int type_hash_eq (const void *, const void *); static hashval_t type_hash_hash (const void *); static hashval_t int_cst_hash_hash (const void *); static int int_cst_hash_eq (const void *, const void *); +static hashval_t cl_option_hash_hash (const void *); +static int cl_option_hash_eq (const void *, const void *); static void print_type_hash_statistics (void); static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); @@ -273,6 +285,12 @@ init_ttree (void) int_cst_node = make_node (INTEGER_CST); + cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash, + cl_option_hash_eq, NULL); + + cl_optimization_node = make_node (OPTIMIZATION_NODE); + cl_target_option_node = make_node (TARGET_OPTION_NODE); + tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1; @@ -505,6 +523,8 @@ tree_code_size (enum tree_code code) case STATEMENT_LIST: return sizeof (struct tree_statement_list); case BLOCK: return sizeof (struct tree_block); case CONSTRUCTOR: return sizeof (struct tree_constructor); + case OPTIMIZATION_NODE: return sizeof (struct tree_optimization_option); + case TARGET_OPTION_NODE: return sizeof (struct tree_target_option); default: return lang_hooks.tree_size (code); @@ -2427,6 +2447,8 @@ tree_node_structure (const_tree t) case CONSTRUCTOR: return TS_CONSTRUCTOR; case TREE_BINFO: return TS_BINFO; case OMP_CLAUSE: return TS_OMP_CLAUSE; + case OPTIMIZATION_NODE: return TS_OPTIMIZATION; + case TARGET_OPTION_NODE: return TS_TARGET_OPTION; default: gcc_unreachable (); @@ -8942,4 +8964,132 @@ block_nonartificial_location (tree block) return ret; } +/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq + nodes. */ + +/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */ + +static hashval_t +cl_option_hash_hash (const void *x) +{ + const_tree const t = (const_tree) x; + const char *p; + size_t i; + size_t len = 0; + hashval_t hash = 0; + + if (TREE_CODE (t) == OPTIMIZATION_NODE) + { + p = (const char *)TREE_OPTIMIZATION (t); + len = sizeof (struct cl_optimization); + } + + else if (TREE_CODE (t) == TARGET_OPTION_NODE) + { + p = (const char *)TREE_TARGET_OPTION (t); + len = sizeof (struct cl_target_option); + } + + else + gcc_unreachable (); + + /* assume most opt flags are just 0/1, some are 2-3, and a few might be + something else. */ + for (i = 0; i < len; i++) + if (p[i]) + hash = (hash << 4) ^ ((i << 2) | p[i]); + + return hash; +} + +/* Return nonzero if the value represented by *X (an OPTIMIZATION or + TARGET_OPTION tree node) is the same as that given by *Y, which is the + same. */ + +static int +cl_option_hash_eq (const void *x, const void *y) +{ + const_tree const xt = (const_tree) x; + const_tree const yt = (const_tree) y; + const char *xp; + const char *yp; + size_t len; + + if (TREE_CODE (xt) != TREE_CODE (yt)) + return 0; + + if (TREE_CODE (xt) == OPTIMIZATION_NODE) + { + xp = (const char *)TREE_OPTIMIZATION (xt); + yp = (const char *)TREE_OPTIMIZATION (yt); + len = sizeof (struct cl_optimization); + } + + else if (TREE_CODE (xt) == TARGET_OPTION_NODE) + { + xp = (const char *)TREE_TARGET_OPTION (xt); + yp = (const char *)TREE_TARGET_OPTION (yt); + len = sizeof (struct cl_target_option); + } + + else + gcc_unreachable (); + + return (memcmp (xp, yp, len) == 0); +} + +/* Build an OPTIMIZATION_NODE based on the current options. */ + +tree +build_optimization_node (void) +{ + tree t; + void **slot; + + /* Use the cache of optimization nodes. */ + + cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node)); + + slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT); + t = (tree) *slot; + if (!t) + { + /* Insert this one into the hash table. */ + t = cl_optimization_node; + *slot = t; + + /* Make a new node for next time round. */ + cl_optimization_node = make_node (OPTIMIZATION_NODE); + } + + return t; +} + +/* Build a TARGET_OPTION_NODE based on the current options. */ + +tree +build_target_option_node (void) +{ + tree t; + void **slot; + + /* Use the cache of optimization nodes. */ + + cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node)); + + slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT); + t = (tree) *slot; + if (!t) + { + /* Insert this one into the hash table. */ + t = cl_target_option_node; + *slot = t; + + /* Make a new node for next time round. */ + cl_target_option_node = make_node (TARGET_OPTION_NODE); + } + + return t; +} + #include "gt-tree.h" |