This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi! Here is a port of the r148760 trunk commit to vta branch, on top of the patch I've posted yesterday. On the HTML401F.class testcase from x86_64-linux bootstrap the compile times and maximum memory usage are: maxVIRT maxRSS TIME vanilla VTA 2973004 2880412 24:47 VTA with 1st patch 2972964 2880396 18:54 VTA with both patches 1696492 1603936 17:55 So while the patch I've posted yesterday mainly improved compile time, this one shaves off almost 1.3GB of memory used by the jc1 process. I've bootstrapped/regtested this on x86_64-linux with the patch from yesterday, this patch and the attached first P2-checking patch on top of it for some extra checking. Not sure if that checking isn't too ugly (looking at hashtab entries bounds) or expensive even for ENABLE_CHECKING (the !dataflow_set_different assert, so I'm not including that in this patch. There are some small differences in debuginfo generated by this patch, but they don't look wrong to me. The last attached patch on top of it are changes which result in no debuginfo differences on a > 2 x 500 preprocessed sources (-m32 and -m64) set, but means we no longer can share any hashtables if a basic block had two or more predecessors, so the patch is meant mainly to show what changes in this large patch actually can make a difference in the debuginfo. It is mainly preferring variable objects from the former dst set (i.e. one where we accumulate merges into) instead of from src (the bb we are merging into it). 2009-06-26 Jakub Jelinek <jakub@redhat.com> * var-tracking.c (decl_or_value): Change from struct to just void * typedef. (struct shared_hash_def, shared_hash): New types. (dataflow_set): Change vars type from htab_t to shared_hash. Add traversed_vars. (shared_hash_pool, empty_shared_hash): New variables. (dv_is_decl_p, dv_is_value_p, dv_as_decl, dv_as_value, dv_as_opaque, dv_from_decl, dv_from_value): Adjust for decl_or_value changes. (variable_htab_eq): Don't expect y to be a pointer to decl_or_value, but decl_or_value itself. (vars_clear): Removed. (shared_hash_shared, shared_hash_htab, shared_hash_copy, shared_hash_find_slot_unshare, shared_hash_find_slot, shared_hash_find_slot_noinsert, shared_hash_find, shared_hash_find_slot_unshare_1, shared_hash_find_slot_1, shared_hash_find_slot_noinsert_1, shared_hash_find_1): New static inlines. (shared_hash_unshare, shared_hash_destroy): New functions. (dst_can_be_shared): New variable. (unshare_variable): Add set argument. Unshare set->vars if shared, use shared_hash_*. Clear dst_can_be_shared. If set->traversed_vars is non-NULL and different from set->vars, look up slot again instead of using the passed in slot. (vars_copy_1): Pass src->dv to htab_find* instead of &src->dv. (vars_copy): Use htab_traverse_noresize instead of htab_traverse. (get_init_value, find_src_set_src, dump_dataflow_set, clobber_variable_part, emit_notes_for_differences, val_reset): Use shared_hash_*. (dataflow_set_init): Remove second argument, set vars to empty_shared_hash instead of creating a new htab. (dataflow_set_clear): Call shared_hash_destroy and set vars to empty_shared_hash instead of calling vars_clear. (dataflow_set_copy): Don't call vars_copy, instead just share the src htab with dst. (variable_union): Use shared_hash_*, use initially NO_INSERT lookup if set->vars is shared. Don't keep slot cleared before calling unshare_variable. Unshare set->vars if needed. Adjust unshare_variable callers. Clear dst_can_be_shared if needed. Even ->refcount == 1 vars must be unshared if set->vars is shared and var needs to be modified. (variable_canonicalize): New function. (dataflow_set_union): If dst->vars is empty, just share src->vars with dst->vars and traverse with variable_canonicalize to canonicalize and unshare what is needed. (find_loc_in_1pdv, find_mem_expr_in_1pdv, vt_expand_loc_callback): Use htab_find_with_hash instead of htab_find_slot_with_hash, pass dv to it instead of &dv. (struct dfset_merge): Add src_onepart_cnt field. (intersect_loc_chains, canonicalize_values_mark, canonicalize_values_star): Use shared_hash_*. (variable_merge_over_cur): Likewise. Clear dst_can_be_shared if needed. Decrement dsm->src_onepart_cnt if s2var found. Prefer s2var over s1var when not different. (variable_merge_over_src): Call variable_canonicalize after inserting the var into the hashtable instead of calling variable_union. For onepart dv increment dsm->src_onepart_cnt. (dataflow_set_merge): Create a new unshared empty hashtab for src, traverse first with variable_merge_over_src and then with variable_merge_over_cur, set dst_can_be_shared if dsm.src_onepart_cnt is non-zero. (dataflow_set_equiv_regs, variable_post_merge_perm_vals, dataflow_post_merge_adjust): Use shared_hash_*. (variable_post_merge_new_vals): Likewise. Adjust unshare_variable and dataflow_set_init callers. (dataflow_set_preserve_mem_locs, dataflow_set_remove_mem_locs): Use shared_hash_*. Adjust unshare_variable and variable_was_changed callers. (dataflow_set_clear_at_call): Use shared_hash_*. (dataflow_set_different_1): Pass var1->dv instead of &var1->dv to htab_find_with_hash. (dataflow_set_different): If old_set and new_set use the same shared htab, they aren't different. If number of htab elements is different, htabs are different. Use shared_hash_*. (dataflow_set_destroy): Call shared_hash_destroy instead of htab_delete. (compute_bb_dataflow, emit_notes_in_bb, vt_emit_notes): Don't pass second argument to dataflow_set_init. (vt_initialize): Likewise. Initialize shared_hash_pool and empty_shared_hash, move bb in/out initialization afterwards. Use variable_htab_free instead of NULL as changed_variables del hook. (vt_find_locations): Use shared_hash_*. Use htab_size and htab_elements instead of ->size and ->n_elements. Remove code to print out differences with -fdump-rtl-vartrack-details. Initialize dst_can_be_shared, if it is true after merges and adjust, share in->vars with first_out->out->vars. (variable_was_changed): Change type of second argument to pointer to dataflow_set. When inserting var into changed_variables, bump refcount. Unshare set->vars if set is shared htab and slot needs to be cleared. Call htab_find_slot_with_hash with var->dv instead of &var->dv. (set_slot_part): Use shared_hash_*. Unshare set->vars if needed. Even ->refcount == 1 vars must be unshared if set->vars is shared and var needs to be modified. Adjust variable_was_changed caller. (set_variable_part): Use shared_hash_*. If iopt is INSERT, unshare set->vars if shared and dv hasn't been found. (delete_slot_part): Use shared_hash_*. Even ->refcount == 1 vars must be unshared if set->vars is shared and var needs to be modified. Adjust variable_was_changed caller. (delete_variable_part): Use shared_hash_*. (emit_note_insn_var_location): Don't pool_free var. (emit_notes_for_changes): Change last argument to shared_hash. (emit_notes_for_differences_1): Initialize empty_var->refcount to 0 instead of 1. Pass old_var->dv instead of &old_var->dv to htab_find_with_hash. (emit_notes_for_differences_2): Pass new_var->dv instead of &new_var->dv to htab_find_with_hash. (vt_finalize): Call htab_delete on empty_shared_hash->htab and free_alloc_pool on shared_hash_pool. --- gcc/var-tracking.c.jj 2009-06-25 12:05:23.000000000 +0200 +++ gcc/var-tracking.c 2009-06-25 20:12:15.000000000 +0200 @@ -180,11 +180,7 @@ typedef struct micro_operation_def /* A declaration of a variable, or an RTL value being handled like a declaration. */ -typedef struct decl_or_value -{ - /* An opaque pointer to the decl or the value. */ - void *ptr; -} decl_or_value; +typedef void *decl_or_value; /* Structure for passing some other parameters to function emit_note_insn_var_location. */ @@ -219,6 +215,17 @@ typedef struct attrs_def HOST_WIDE_INT offset; } *attrs; +/* Structure holding a refcounted hash table. If refcount > 1, + it must be first unshared before modified. */ +typedef struct shared_hash_def +{ + /* Reference count. */ + int refcount; + + /* Actual hash table. */ + htab_t htab; +} *shared_hash; + /* Structure holding the IN or OUT set for a basic block. */ typedef struct dataflow_set_def { @@ -229,7 +236,10 @@ typedef struct dataflow_set_def attrs regs[FIRST_PSEUDO_REGISTER]; /* Variable locations. */ - htab_t vars; + shared_hash vars; + + /* Vars that is being traversed. */ + shared_hash traversed_vars; } dataflow_set; /* The structure (one for each basic block) containing the information @@ -331,12 +341,18 @@ static alloc_pool valvar_pool; /* Alloc pool for struct location_chain_def. */ static alloc_pool loc_chain_pool; +/* Alloc pool for struct shared_hash_def. */ +static alloc_pool shared_hash_pool; + /* Changed variables, notes will be emitted for them. */ static htab_t changed_variables; /* Shall notes be emitted? */ static bool emit_notes; +/* Empty shared hashtable. */ +static shared_hash empty_shared_hash; + /* Scratch register bitmap used by cselib_expand_value_rtx. */ static bitmap scratch_regs = NULL; @@ -362,8 +378,7 @@ static void attrs_list_insert (attrs *, static void attrs_list_copy (attrs *, attrs); static void attrs_list_union (attrs *, attrs); -static void vars_clear (htab_t); -static variable unshare_variable (void **slot, variable var, +static variable unshare_variable (dataflow_set *set, void **slot, variable var, enum var_init_status); static int vars_copy_1 (void **, void *); static void vars_copy (htab_t, htab_t); @@ -378,11 +393,12 @@ static void var_mem_delete_and_set (data enum var_init_status, rtx); static void var_mem_delete (dataflow_set *, rtx, bool); -static void dataflow_set_init (dataflow_set *, int); +static void dataflow_set_init (dataflow_set *); static void dataflow_set_clear (dataflow_set *); static void dataflow_set_copy (dataflow_set *, dataflow_set *); static int variable_union_info_cmp_pos (const void *, const void *); static int variable_union (void **, void *); +static int variable_canonicalize (void **, void *); static void dataflow_set_union (dataflow_set *, dataflow_set *); static location_chain find_loc_in_1pdv (rtx, variable, htab_t); static bool canon_value_cmp (rtx, rtx); @@ -414,7 +430,7 @@ static void dump_vars (htab_t); static void dump_dataflow_set (dataflow_set *); static void dump_dataflow_sets (void); -static void variable_was_changed (variable, htab_t); +static void variable_was_changed (variable, dataflow_set *); static void set_slot_part (dataflow_set *, rtx, void **, decl_or_value, HOST_WIDE_INT, enum var_init_status, rtx); @@ -429,7 +445,7 @@ static void delete_slot_part (dataflow_s static void delete_variable_part (dataflow_set *, rtx, decl_or_value, HOST_WIDE_INT); static int emit_note_insn_var_location (void **, void *); -static void emit_notes_for_changes (rtx, enum emit_note_where, htab_t vars); +static void emit_notes_for_changes (rtx, enum emit_note_where, shared_hash); static int emit_notes_for_differences_1 (void **, void *); static int emit_notes_for_differences_2 (void **, void *); static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *); @@ -684,10 +700,10 @@ adjust_stack_reference (rtx mem, HOST_WI static inline bool dv_is_decl_p (decl_or_value dv) { - if (!dv.ptr) + if (!dv) return false; - if (GET_CODE ((rtx)dv.ptr) == VALUE) + if (GET_CODE ((rtx)dv) == VALUE) return false; return true; @@ -697,7 +713,7 @@ dv_is_decl_p (decl_or_value dv) static inline bool dv_is_value_p (decl_or_value dv) { - return dv.ptr && !dv_is_decl_p (dv); + return dv && !dv_is_decl_p (dv); } /* Return the decl in the decl_or_value. */ @@ -705,7 +721,7 @@ static inline tree dv_as_decl (decl_or_value dv) { gcc_assert (dv_is_decl_p (dv)); - return (tree) dv.ptr; + return (tree) dv; } /* Return the value in the decl_or_value. */ @@ -713,14 +729,14 @@ static inline rtx dv_as_value (decl_or_value dv) { gcc_assert (dv_is_value_p (dv)); - return (rtx)dv.ptr; + return (rtx)dv; } /* Return the opaque pointer in the decl_or_value. */ static inline void * dv_as_opaque (decl_or_value dv) { - return dv.ptr; + return dv; } /* Return true if a decl_or_value must not have more than one variable @@ -766,7 +782,7 @@ dv_from_decl (tree decl) { decl_or_value dv; gcc_assert (!decl || IS_DECL_CODE (TREE_CODE (decl))); - dv.ptr = decl; + dv = decl; return dv; } @@ -776,7 +792,7 @@ dv_from_value (rtx value) { decl_or_value dv; gcc_assert (value); - dv.ptr = value; + dv = value; return dv; } @@ -806,7 +822,7 @@ static int variable_htab_eq (const void *x, const void *y) { const_variable const v = (const_variable) x; - decl_or_value dv = *(decl_or_value const*)y; + decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y); if (dv_as_opaque (v->dv) == dv_as_opaque (dv)) return true; @@ -964,18 +980,137 @@ attrs_list_mpdv_union (attrs *dstp, attr } } -/* Delete all variables from hash table VARS. */ +/* Shared hashtable support. */ + +/* Return true if VARS is shared. */ + +static inline bool +shared_hash_shared (shared_hash vars) +{ + return vars->refcount > 1; +} + +/* Return the hash table for VARS. */ + +static inline htab_t +shared_hash_htab (shared_hash vars) +{ + return vars->htab; +} + +/* Copy variables into a new hash table. */ + +static shared_hash +shared_hash_unshare (shared_hash vars) +{ + shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool); + gcc_assert (vars->refcount > 1); + new_vars->refcount = 1; + new_vars->htab + = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash, + variable_htab_eq, variable_htab_free); + vars_copy (new_vars->htab, vars->htab); + vars->refcount--; + return new_vars; +} + +/* Increment reference counter on VARS and return it. */ + +static inline shared_hash +shared_hash_copy (shared_hash vars) +{ + vars->refcount++; + return vars; +} + +/* Decrement reference counter and destroy hash table if not shared + anymore. */ static void -vars_clear (htab_t vars) +shared_hash_destroy (shared_hash vars) +{ + gcc_assert (vars->refcount > 0); + if (--vars->refcount == 0) + { + htab_delete (vars->htab); + pool_free (shared_hash_pool, vars); + } +} + +/* Unshare *PVARS if shared and return slot for DV. If INS is + INSERT, insert it if not already present. */ + +static inline void ** +shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv, + hashval_t dvhash, enum insert_option ins) +{ + if (shared_hash_shared (*pvars)) + *pvars = shared_hash_unshare (*pvars); + return htab_find_slot_with_hash (shared_hash_htab (*pvars), dv, dvhash, ins); +} + +static inline void ** +shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv, + enum insert_option ins) +{ + return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins); +} + +/* Return slot for DV, if it is already present in the hash table. + If it is not present, insert it only VARS is not shared, otherwise + return NULL. */ + +static inline void ** +shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash) +{ + return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash, + shared_hash_shared (vars) + ? NO_INSERT : INSERT); +} + +static inline void ** +shared_hash_find_slot (shared_hash vars, decl_or_value dv) +{ + return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv)); +} + +/* Return slot for DV only if it is already present in the hash table. */ + +static inline void ** +shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv, + hashval_t dvhash) { - htab_empty (vars); + return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash, + NO_INSERT); +} + +static inline void ** +shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv) +{ + return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv)); } +/* Return variable for DV or NULL if not already present in the hash + table. */ + +static inline variable +shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash) +{ + return (variable) htab_find_with_hash (shared_hash_htab (vars), dv, dvhash); +} + +static inline variable +shared_hash_find (shared_hash vars, decl_or_value dv) +{ + return shared_hash_find_1 (vars, dv, dv_htab_hash (dv)); +} + +static bool dst_can_be_shared; + /* Return a copy of a variable VAR and insert it to dataflow set SET. */ static variable -unshare_variable (void **slot, variable var, +unshare_variable (dataflow_set *set, void **slot, variable var, enum var_init_status initialized) { variable new_var; @@ -1022,6 +1157,11 @@ unshare_variable (void **slot, variable new_var->var_part[i].cur_loc = NULL; } + dst_can_be_shared = false; + if (shared_hash_shared (set->vars)) + slot = shared_hash_find_slot_unshare (&set->vars, var->dv, NO_INSERT); + else if (set->traversed_vars && set->vars != set->traversed_vars) + slot = shared_hash_find_slot_noinsert (set->vars, var->dv); *slot = new_var; return new_var; } @@ -1039,7 +1179,7 @@ vars_copy_1 (void **slot, void *data) src = (variable) *slot; src->refcount++; - dstp = htab_find_slot_with_hash (dst, &src->dv, + dstp = htab_find_slot_with_hash (dst, src->dv, dv_htab_hash (src->dv), INSERT); *dstp = src; @@ -1053,8 +1193,7 @@ vars_copy_1 (void **slot, void *data) static void vars_copy (htab_t dst, htab_t src) { - vars_clear (dst); - htab_traverse (src, vars_copy_1, dst); + htab_traverse_noresize (src, vars_copy_1, dst); } /* Map a decl to its main debug decl. */ @@ -1108,7 +1247,6 @@ var_reg_set (dataflow_set *set, rtx loc, static enum var_init_status get_init_value (dataflow_set *set, rtx loc, decl_or_value dv) { - void **slot; variable var; int i; enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN; @@ -1116,11 +1254,9 @@ get_init_value (dataflow_set *set, rtx l if (! flag_var_tracking_uninit) return VAR_INIT_STATUS_INITIALIZED; - slot = htab_find_slot_with_hash (set->vars, &dv, - dv_htab_hash (dv), NO_INSERT); - if (slot) + var = shared_hash_find (set->vars, dv); + if (var) { - var = (variable) *slot; for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++) { location_chain nextp; @@ -1339,17 +1475,11 @@ val_store (dataflow_set *set, rtx val, r static void val_reset (dataflow_set *set, decl_or_value dv) { - void **slot = htab_find_slot_with_hash (set->vars, &dv, dv_htab_hash (dv), - NO_INSERT); - variable var; + variable var = shared_hash_find (set->vars, dv) ; location_chain node; rtx cval; - if (!slot) - return; - - var = (variable)*slot; - if (!var->n_var_parts) + if (!var || !var->n_var_parts) return; gcc_assert (var->n_var_parts == 1); @@ -1474,12 +1604,12 @@ val_resolve (dataflow_set *set, rtx val, VARS_SIZE is the initial size of hash table VARS. */ static void -dataflow_set_init (dataflow_set *set, int vars_size) +dataflow_set_init (dataflow_set *set) { init_attrs_list_set (set->regs); - set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq, - variable_htab_free); + set->vars = shared_hash_copy (empty_shared_hash); set->stack_adjust = 0; + set->traversed_vars = NULL; } /* Delete the contents of dataflow set SET. */ @@ -1492,7 +1622,8 @@ dataflow_set_clear (dataflow_set *set) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) attrs_list_clear (&set->regs[i]); - vars_clear (set->vars); + shared_hash_destroy (set->vars); + set->vars = shared_hash_copy (empty_shared_hash); } /* Copy the contents of dataflow set SRC to DST. */ @@ -1505,7 +1636,8 @@ dataflow_set_copy (dataflow_set *dst, da for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) attrs_list_copy (&dst->regs[i], src->regs[i]); - vars_copy (dst->vars, src->vars); + shared_hash_destroy (dst->vars); + dst->vars = shared_hash_copy (src->vars); dst->stack_adjust = src->stack_adjust; } @@ -1559,13 +1691,17 @@ variable_union (void **slot, void *data) int i, j, k; src = (variable) *slot; - dstp = htab_find_slot_with_hash (set->vars, &src->dv, - dv_htab_hash (src->dv), - INSERT); - if (!*dstp) + dstp = shared_hash_find_slot (set->vars, src->dv); + if (!dstp || !*dstp) { src->refcount++; + dst_can_be_shared = false; + if (!dstp) + dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT); + + *dstp = src; + /* If CUR_LOC of some variable part is not the first element of the location chain we are going to change it so we have to make a copy of the variable. */ @@ -1587,10 +1723,8 @@ variable_union (void **slot, void *data) if (! flag_var_tracking_uninit) status = VAR_INIT_STATUS_INITIALIZED; - unshare_variable (dstp, src, status); + unshare_variable (set, dstp, src, status); } - else - *dstp = src; /* Continue traversing the hash table. */ return 1; @@ -1625,9 +1759,9 @@ variable_union (void **slot, void *data) { location_chain nnode; - if (dst->refcount != 1) + if (dst->refcount != 1 || shared_hash_shared (set->vars)) { - dst = unshare_variable (dstp, dst, + dst = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_INITIALIZED); goto restart_onepart_unshared; } @@ -1678,13 +1812,14 @@ variable_union (void **slot, void *data) thus there are at most MAX_VAR_PARTS different offsets. */ gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS); - if (dst->refcount > 1 && dst->n_var_parts != k) + if ((dst->refcount > 1 || shared_hash_shared (set->vars)) + && dst->n_var_parts != k) { enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; if (! flag_var_tracking_uninit) status = VAR_INIT_STATUS_INITIALIZED; - dst = unshare_variable (dstp, dst, status); + dst = unshare_variable (set, dstp, dst, status); } i = src->n_var_parts - 1; @@ -1708,7 +1843,7 @@ variable_union (void **slot, void *data) /* If DST is shared compare the location chains. If they are different we will modify the chain in DST with high probability so make a copy of DST. */ - if (dst->refcount > 1) + if (dst->refcount > 1 || shared_hash_shared (set->vars)) { for (node = src->var_part[i].loc_chain, node2 = dst->var_part[j].loc_chain; node && node2; @@ -1725,7 +1860,8 @@ variable_union (void **slot, void *data) } } if (node || node2) - dst = unshare_variable (dstp, dst, VAR_INIT_STATUS_UNKNOWN); + dst = unshare_variable (set, dstp, dst, + VAR_INIT_STATUS_UNKNOWN); } src_l = 0; @@ -1861,6 +1997,46 @@ variable_union (void **slot, void *data) return 1; } +/* Like variable_union, but only used when doing dataflow_set_union + into an empty hashtab. To allow sharing, dst is initially shared + with src (so all variables are "copied" from src to dst hashtab), + so only unshare_variable for variables that need canonicalization + are needed. */ + +static int +variable_canonicalize (void **slot, void *data) +{ + variable src; + dataflow_set *set = (dataflow_set *) data; + int k; + + src = *(variable *) slot; + + /* If CUR_LOC of some variable part is not the first element of + the location chain we are going to change it so we have to make + a copy of the variable. */ + for (k = 0; k < src->n_var_parts; k++) + { + gcc_assert (!src->var_part[k].loc_chain == !src->var_part[k].cur_loc); + if (src->var_part[k].loc_chain) + { + gcc_assert (src->var_part[k].cur_loc); + if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc) + break; + } + } + if (k < src->n_var_parts) + { + enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; + + if (! flag_var_tracking_uninit) + status = VAR_INIT_STATUS_INITIALIZED; + + unshare_variable (set, slot, src, status); + } + return 1; +} + /* Compute union of dataflow sets SRC and DST and store it to DST. */ static void @@ -1871,7 +2047,16 @@ dataflow_set_union (dataflow_set *dst, d for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) attrs_list_union (&dst->regs[i], src->regs[i]); - htab_traverse (src->vars, variable_union, dst); + if (dst->vars == empty_shared_hash) + { + shared_hash_destroy (dst->vars); + dst->vars = shared_hash_copy (src->vars); + dst->traversed_vars = dst->vars; + htab_traverse (shared_hash_htab (dst->vars), variable_canonicalize, dst); + dst->traversed_vars = NULL; + } + else + htab_traverse (shared_hash_htab (src->vars), variable_union, dst); } /* Whether the value is currently being expanded. */ @@ -1931,14 +2116,14 @@ find_loc_in_1pdv (rtx loc, variable var, && !VALUE_RECURSED_INTO (node->loc)) { decl_or_value dv = dv_from_value (node->loc); - void **slot = htab_find_slot_with_hash (vars, &dv, dv_htab_hash (dv), - NO_INSERT); + variable var = (variable) + htab_find_with_hash (vars, dv, dv_htab_hash (dv)); - if (slot) + if (var) { location_chain where; VALUE_RECURSED_INTO (node->loc) = true; - if ((where = find_loc_in_1pdv (loc, (variable)*slot, vars))) + if ((where = find_loc_in_1pdv (loc, var, vars))) { VALUE_RECURSED_INTO (node->loc) = false; return where; @@ -1959,6 +2144,8 @@ struct dfset_merge dataflow_set *cur; /* The set that may contain the other dv we are to merge with. */ dataflow_set *src; + /* Number of onepart dvs in src. */ + int src_onepart_cnt; }; /* Insert LOC in *DNODE, if it's not there yet. The list must be in @@ -2007,7 +2194,8 @@ intersect_loc_chains (rtx val, location_ if (s1node->loc == val) continue; - if ((found = find_loc_in_1pdv (s1node->loc, s2var, s2set->vars))) + if ((found = find_loc_in_1pdv (s1node->loc, s2var, + shared_hash_htab (s2set->vars)))) { insert_into_intersection (dest, s1node->loc, MIN (s1node->init, found->init)); @@ -2018,14 +2206,9 @@ intersect_loc_chains (rtx val, location_ && !VALUE_RECURSED_INTO (s1node->loc)) { decl_or_value dv = dv_from_value (s1node->loc); - void **slot = htab_find_slot_with_hash (s1set->vars, - &dv, dv_htab_hash (dv), - NO_INSERT); - - if (slot) + variable svar = shared_hash_find (s1set->vars, dv); + if (svar) { - variable svar = (variable)*slot; - if (svar->n_var_parts == 1) { VALUE_RECURSED_INTO (s1node->loc) = true; @@ -2298,9 +2481,8 @@ canonicalize_values_mark (void **slot, v else { decl_or_value odv = dv_from_value (node->loc); - void **oslot = htab_find_slot_with_hash (set->vars, &odv, - dv_htab_hash (odv), - NO_INSERT); + void **oslot = shared_hash_find_slot_noinsert (set->vars, odv); + #if 0 && ENABLE_CHECKING variable ovar; location_chain onode; @@ -2396,8 +2578,7 @@ canonicalize_values_star (void **slot, v restart_with_cval: VALUE_RECURSED_INTO (cval) = false; dv = dv_from_value (cval); - slot = htab_find_slot_with_hash (set->vars, &dv, dv_htab_hash (dv), - NO_INSERT); + slot = shared_hash_find_slot_noinsert (set->vars, dv); if (!slot) { gcc_assert (dv_is_decl_p (var->dv)); @@ -2421,8 +2602,7 @@ canonicalize_values_star (void **slot, v /* Push values to the canonical one. */ cdv = dv_from_value (cval); - cslot = htab_find_slot_with_hash (set->vars, &cdv, dv_htab_hash (cdv), - NO_INSERT); + cslot = shared_hash_find_slot_noinsert (set->vars, cdv); for (node = var->var_part[0].loc_chain; node; node = node->next) if (node->loc != cval) @@ -2572,7 +2752,7 @@ variable_merge_over_cur (void **s1slot, { struct dfset_merge *dsm = (struct dfset_merge *)data; dataflow_set *dst = dsm->dst; - void **s2slot, **dstslot; + void **dstslot; variable s1var = (variable) *s1slot; variable s2var, dvar = NULL; decl_or_value dv = s1var->dv; @@ -2599,18 +2779,19 @@ variable_merge_over_cur (void **s1slot, else val = NULL; - s2slot = htab_find_slot_with_hash (dsm->src->vars, &dv, dvhash, NO_INSERT); - if (!s2slot) - return 1; - - s2var = (variable) *s2slot; + s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash); + if (!s2var) + { + dst_can_be_shared = false; + return 1; + } + dsm->src_onepart_cnt--; gcc_assert (s2var->var_part[0].loc_chain); gcc_assert (s2var->n_var_parts == 1); gcc_assert (s2var->var_part[0].offset == 0); - dstslot = htab_find_slot_with_hash (dst->vars, &dv, dvhash, NO_INSERT); - + dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash); if (dstslot) { dvar = (variable)*dstslot; @@ -2627,13 +2808,15 @@ variable_merge_over_cur (void **s1slot, if (!dstslot && !onepart_variable_different_p (s1var, s2var)) { - dstslot = htab_find_slot_with_hash (dst->vars, &dv, dvhash, - INSERT); - *dstslot = dvar = s1var; + dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv, + dvhash, INSERT); + *dstslot = dvar = s2var; dvar->refcount++; } else { + dst_can_be_shared = false; + intersect_loc_chains (val, nodep, dsm, s1var->var_part[0].loc_chain, s2var); @@ -2649,8 +2832,9 @@ variable_merge_over_cur (void **s1slot, dvar->var_part[0].loc_chain = node; dvar->var_part[0].cur_loc = node->loc; - dstslot = htab_find_slot_with_hash (dst->vars, &dv, dvhash, - INSERT); + dstslot + = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash, + INSERT); gcc_assert (!*dstslot); *dstslot = dvar; } @@ -2719,12 +2903,13 @@ variable_merge_over_cur (void **s1slot, node->init, NULL, INSERT); } - dstslot = htab_find_slot_with_hash (dst->vars, &dv, dvhash, - NO_INSERT); + dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash); gcc_assert (*dstslot == dvar); canonicalize_values_star (dstslot, dst); - gcc_assert (dstslot == htab_find_slot_with_hash (dst->vars, &dv, - dvhash, NO_INSERT)); +#ifdef ENABLE_CHECKING + gcc_assert (dstslot + == shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash)); +#endif dvar = (variable)*dstslot; } else @@ -2761,8 +2946,12 @@ variable_merge_over_cur (void **s1slot, if (GET_CODE (node->loc) == VALUE) { decl_or_value dv = dv_from_value (node->loc); - void **slot = htab_find_slot_with_hash (dst->vars, &dv, - dv_htab_hash (dv), + void **slot = NULL; + + if (shared_hash_shared (dst->vars)) + slot = shared_hash_find_slot_noinsert (dst->vars, dv); + if (!slot) + slot = shared_hash_find_slot_unshare (&dst->vars, dv, INSERT); if (!*slot) { @@ -2780,31 +2969,37 @@ variable_merge_over_cur (void **s1slot, } } - dstslot = htab_find_slot_with_hash (dst->vars, &dv, dvhash, - NO_INSERT); + dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash); gcc_assert (*dstslot == dvar); canonicalize_values_star (dstslot, dst); - gcc_assert (dstslot == htab_find_slot_with_hash (dst->vars, &dv, - dvhash, - NO_INSERT)); +#ifdef ENABLE_CHECKING + gcc_assert (dstslot + == shared_hash_find_slot_noinsert_1 (dst->vars, + dv, dvhash)); +#endif dvar = (variable)*dstslot; } } - if (!onepart_variable_different_p (dvar, s1var)) + if (!onepart_variable_different_p (dvar, s2var)) { variable_htab_free (dvar); - *dstslot = dvar = s1var; + *dstslot = dvar = s2var; dvar->refcount++; } - else if (s2var != s1var && !onepart_variable_different_p (dvar, s2var)) + else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var)) { variable_htab_free (dvar); - *dstslot = dvar = s2var; + *dstslot = dvar = s1var; dvar->refcount++; + dst_can_be_shared = false; + } + else + { + if (dvar->refcount == 1) + dvar->var_part[0].cur_loc = dvar->var_part[0].loc_chain->loc; + dst_can_be_shared = false; } - else if (dvar->refcount == 1) - dvar->var_part[0].cur_loc = dvar->var_part[0].loc_chain->loc; return 1; } @@ -2824,8 +3019,14 @@ variable_merge_over_src (void **s2slot, bool onepart = dv_onepart_p (dv); if (!onepart) - return variable_union (s2slot, dst); + { + void **dstp = shared_hash_find_slot (dst->vars, dv); + *dstp = s2var; + s2var->refcount++; + return variable_canonicalize (dstp, dst); + } + dsm->src_onepart_cnt++; return 1; } @@ -2838,9 +3039,18 @@ dataflow_set_merge (dataflow_set *dst, d dataflow_set src2 = *dst; struct dfset_merge dsm; int i; + size_t src_elems, dst_elems; - dataflow_set_init (dst, MAX (htab_elements (src->vars), - htab_elements (src2.vars))); + src_elems = htab_elements (shared_hash_htab (src->vars)); + dst_elems = htab_elements (shared_hash_htab (src2.vars)); + dataflow_set_init (dst); + dst->stack_adjust = src2.stack_adjust; + shared_hash_destroy (dst->vars); + dst->vars = (shared_hash) pool_alloc (shared_hash_pool); + dst->vars->refcount = 1; + dst->vars->htab + = htab_create (MAX (src_elems, dst_elems), variable_htab_hash, + variable_htab_eq, variable_htab_free); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) attrs_list_mpdv_union (&dst->regs[i], src->regs[i], src2.regs[i]); @@ -2848,9 +3058,15 @@ dataflow_set_merge (dataflow_set *dst, d dsm.dst = dst; dsm.src = &src2; dsm.cur = src; + dsm.src_onepart_cnt = 0; - htab_traverse (dsm.cur->vars, variable_merge_over_cur, &dsm); - htab_traverse (dsm.src->vars, variable_merge_over_src, &dsm); + htab_traverse (shared_hash_htab (dsm.src->vars), variable_merge_over_src, + &dsm); + htab_traverse (shared_hash_htab (dsm.cur->vars), variable_merge_over_cur, + &dsm); + + if (dsm.src_onepart_cnt) + dst_can_be_shared = false; dataflow_set_destroy (&src2); } @@ -2923,9 +3139,7 @@ dataflow_set_equiv_regs (dataflow_set *s continue; } - slot = htab_find_slot_with_hash (set->vars, &list->dv, - dv_htab_hash (list->dv), - NO_INSERT); + slot = shared_hash_find_slot_noinsert (set->vars, list->dv); canonicalize_values_star (slot, set); if (*listp != list) list = NULL; @@ -3012,7 +3226,7 @@ variable_post_merge_new_vals (void **slo if (var->refcount != 1) { - var = unshare_variable (slot, var, + var = unshare_variable (set, slot, var, VAR_INIT_STATUS_INITIALIZED); goto restart; } @@ -3054,7 +3268,7 @@ variable_post_merge_new_vals (void **slo if (!*dfpm->permp) { *dfpm->permp = XNEW (dataflow_set); - dataflow_set_init (*dfpm->permp, 7); + dataflow_set_init (*dfpm->permp); } for (att = (*dfpm->permp)->regs[REGNO (node->loc)]; @@ -3121,7 +3335,7 @@ variable_post_merge_new_vals (void **slo if (var->refcount != 1) { - var = unshare_variable (slot, var, + var = unshare_variable (set, slot, var, VAR_INIT_STATUS_INITIALIZED); goto restart; } @@ -3143,9 +3357,7 @@ variable_post_merge_new_vals (void **slo cval = v->val_rtx; cdv = dv_from_value (cval); - oslot = htab_find_slot_with_hash - (set->vars, &cdv, dv_htab_hash (cdv), NO_INSERT); - + oslot = shared_hash_find_slot_noinsert (set->vars, cdv); if (oslot) set_slot_part (set, node->loc, oslot, cdv, 0, VAR_INIT_STATUS_INITIALIZED, NULL_RTX); @@ -3154,7 +3366,7 @@ variable_post_merge_new_vals (void **slo if (!*dfpm->permp) { *dfpm->permp = XNEW (dataflow_set); - dataflow_set_init (*dfpm->permp, 7); + dataflow_set_init (*dfpm->permp); } set_variable_part (*dfpm->permp, node->loc, cdv, 0, @@ -3182,9 +3394,8 @@ variable_post_merge_perm_vals (void **ps { struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info; dataflow_set *set = dfpm->set; - variable pvar = (variable)*pslot; + variable pvar = (variable)*pslot, var; location_chain pnode; - void **slot; decl_or_value dv; attrs att; @@ -3197,12 +3408,10 @@ variable_post_merge_perm_vals (void **ps dv = pvar->dv; - slot = htab_find_slot_with_hash (set->vars, &dv, dv_htab_hash (dv), - NO_INSERT); - - if (slot) + var = shared_hash_find (set->vars, dv); + if (var) { - if (find_loc_in_1pdv (pnode->loc, (variable)*slot, set->vars)) + if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars))) return 1; val_reset (set, dv); } @@ -3243,10 +3452,12 @@ dataflow_post_merge_adjust (dataflow_set dfpm.set = set; dfpm.permp = permp; - htab_traverse (set->vars, variable_post_merge_new_vals, &dfpm); + htab_traverse (shared_hash_htab (set->vars), variable_post_merge_new_vals, + &dfpm); if (*permp) - htab_traverse ((*permp)->vars, variable_post_merge_perm_vals, &dfpm); - htab_traverse (set->vars, canonicalize_values_star, set); + htab_traverse (shared_hash_htab ((*permp)->vars), + variable_post_merge_perm_vals, &dfpm); + htab_traverse (shared_hash_htab (set->vars), canonicalize_values_star, set); } /* Return a node whose loc is a MEM that refers to EXPR in the @@ -3258,7 +3469,6 @@ find_mem_expr_in_1pdv (tree expr, rtx va { location_chain node; decl_or_value dv; - void **slot; variable var; location_chain where = NULL; @@ -3270,14 +3480,11 @@ find_mem_expr_in_1pdv (tree expr, rtx va gcc_assert (!VALUE_RECURSED_INTO (val)); dv = dv_from_value (val); - slot = htab_find_slot_with_hash (vars, &dv, dv_htab_hash (dv), NO_INSERT); + var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv)); - if (!slot) + if (!var) return NULL; - var = (variable)*slot; - - gcc_assert (var); gcc_assert (dv_onepart_p (var->dv)); if (!var->n_var_parts) @@ -3315,7 +3522,7 @@ find_mem_expr_in_1pdv (tree expr, rtx va static int dataflow_set_preserve_mem_locs (void **slot, void *data) { - htab_t vars = (htab_t) data; + dataflow_set *set = (dataflow_set *) data; variable var = (variable) *slot; if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv)) @@ -3328,7 +3535,7 @@ dataflow_set_preserve_mem_locs (void **s gcc_assert (var->n_var_parts == 1); - if (var->refcount > 1) + if (var->refcount > 1 || shared_hash_shared (set->vars)) { for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) { @@ -3339,14 +3546,15 @@ dataflow_set_preserve_mem_locs (void **s break; /* We want to move here a MEM that does refer to DECL. */ else if (GET_CODE (loc->loc) == VALUE - && find_mem_expr_in_1pdv (decl, loc->loc, vars)) + && find_mem_expr_in_1pdv (decl, loc->loc, + shared_hash_htab (set->vars))) break; } if (!loc) return 1; - var = unshare_variable (slot, var, VAR_INIT_STATUS_UNKNOWN); + var = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN); gcc_assert (var->n_var_parts == 1); } @@ -3355,8 +3563,9 @@ dataflow_set_preserve_mem_locs (void **s { if (GET_CODE (loc->loc) == VALUE) { - location_chain mem_node = find_mem_expr_in_1pdv (decl, loc->loc, - vars); + location_chain mem_node + = find_mem_expr_in_1pdv (decl, loc->loc, + shared_hash_htab (set->vars)); /* ??? This picks up only one out of multiple MEMs that refer to the same variable. Do we ever need to be @@ -3387,7 +3596,7 @@ dataflow_set_preserve_mem_locs (void **s if (!var->var_part[0].loc_chain) { var->n_var_parts--; - variable_was_changed (var, vars); + variable_was_changed (var, set); } } @@ -3400,7 +3609,7 @@ dataflow_set_preserve_mem_locs (void **s static int dataflow_set_remove_mem_locs (void **slot, void *data) { - htab_t vars = (htab_t) data; + dataflow_set *set = (dataflow_set *) data; variable var = (variable) *slot; if (dv_is_value_p (var->dv)) @@ -3410,7 +3619,7 @@ dataflow_set_remove_mem_locs (void **slo gcc_assert (var->n_var_parts == 1); - if (var->refcount > 1) + if (var->refcount > 1 || shared_hash_shared (set->vars)) { for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) if (GET_CODE (loc->loc) == MEM) @@ -3419,7 +3628,7 @@ dataflow_set_remove_mem_locs (void **slo if (!loc) return 1; - var = unshare_variable (slot, var, VAR_INIT_STATUS_UNKNOWN); + var = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN); gcc_assert (var->n_var_parts == 1); } @@ -3451,7 +3660,7 @@ dataflow_set_remove_mem_locs (void **slo { if (var->n_var_parts && var->var_part[0].loc_chain) var->var_part[0].cur_loc = var->var_part[0].loc_chain->loc; - variable_was_changed (var, vars); + variable_was_changed (var, set); } } @@ -3472,8 +3681,13 @@ dataflow_set_clear_at_call (dataflow_set if (MAY_HAVE_DEBUG_INSNS) { - htab_traverse (set->vars, dataflow_set_preserve_mem_locs, set->vars); - htab_traverse (set->vars, dataflow_set_remove_mem_locs, set->vars); + set->traversed_vars = set->vars; + htab_traverse (shared_hash_htab (set->vars), + dataflow_set_preserve_mem_locs, set); + set->traversed_vars = set->vars; + htab_traverse (shared_hash_htab (set->vars), dataflow_set_remove_mem_locs, + set); + set->traversed_vars = NULL; } } @@ -3590,7 +3804,7 @@ dataflow_set_different_1 (void **slot, v variable var1, var2; var1 = (variable) *slot; - var2 = (variable) htab_find_with_hash (htab, &var1->dv, + var2 = (variable) htab_find_with_hash (htab, var1->dv, dv_htab_hash (var1->dv)); if (!var2) { @@ -3635,7 +3849,7 @@ dataflow_set_different_2 (void **slot, v variable var1, var2; var1 = (variable) *slot; - var2 = (variable) htab_find_with_hash (htab, &var1->dv, + var2 = (variable) htab_find_with_hash (htab, var1->dv, dv_htab_hash (var1->dv)); if (!var2) { @@ -3664,15 +3878,24 @@ dataflow_set_different_2 (void **slot, v static bool dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set) { + if (old_set->vars == new_set->vars) + return false; + + if (htab_elements (shared_hash_htab (old_set->vars)) + != htab_elements (shared_hash_htab (new_set->vars))) + return true; + dataflow_set_different_value = false; - htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars); + htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1, + shared_hash_htab (new_set->vars)); if (!dataflow_set_different_value) { /* We have compared the variables which are in both hash tables so now only check whether there are some variables in NEW_SET->VARS which are not in OLD_SET->VARS. */ - htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars); + htab_traverse (shared_hash_htab (new_set->vars), dataflow_set_different_2, + shared_hash_htab (old_set->vars)); } return dataflow_set_different_value; } @@ -3687,7 +3910,7 @@ dataflow_set_destroy (dataflow_set *set) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) attrs_list_clear (&set->regs[i]); - htab_delete (set->vars); + shared_hash_destroy (set->vars); set->vars = NULL; } @@ -4684,7 +4907,6 @@ find_src_set_src (dataflow_set *set, rtx { tree decl = NULL_TREE; /* The variable being copied around. */ rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */ - void **slot; variable var; location_chain nextp; int i; @@ -4699,12 +4921,9 @@ find_src_set_src (dataflow_set *set, rtx { decl_or_value dv = dv_from_decl (decl); - slot = htab_find_slot_with_hash (set->vars, &dv, - VARIABLE_HASH_VAL (decl), NO_INSERT); - - if (slot) + var = shared_hash_find (set->vars, dv); + if (var) { - var = (variable) *slot; found = false; for (i = 0; i < var->n_var_parts && !found; i++) for (nextp = var->var_part[i].loc_chain; nextp && !found; @@ -4732,7 +4951,7 @@ compute_bb_dataflow (basic_block bb) dataflow_set *in = &VTI (bb)->in; dataflow_set *out = &VTI (bb)->out; - dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3); + dataflow_set_init (&old_out); dataflow_set_copy (&old_out, out); dataflow_set_copy (out, in); @@ -4986,10 +5205,13 @@ compute_bb_dataflow (basic_block bb) if (MAY_HAVE_DEBUG_INSNS) { dataflow_set_equiv_regs (out); - htab_traverse (out->vars, canonicalize_values_mark, out); - htab_traverse (out->vars, canonicalize_values_star, out); + htab_traverse (shared_hash_htab (out->vars), canonicalize_values_mark, + out); + htab_traverse (shared_hash_htab (out->vars), canonicalize_values_star, + out); #if ENABLE_CHECKING - htab_traverse (out->vars, canonicalize_loc_order_check, out); + htab_traverse (shared_hash_htab (out->vars), + canonicalize_loc_order_check, out); #endif } changed = dataflow_set_different (&old_out, out); @@ -5054,35 +5276,29 @@ vt_find_locations (void) SET_BIT (visited, bb->index); - if (VTI (bb)->in.vars) + if (dump_file && VTI (bb)->in.vars) { - htabsz -= VTI (bb)->in.vars->size + VTI (bb)->out.vars->size; - oldinsz = VTI (bb)->in.vars->n_elements; - oldoutsz = VTI (bb)->out.vars->n_elements; + htabsz + -= htab_size (shared_hash_htab (VTI (bb)->in.vars)) + + htab_size (shared_hash_htab (VTI (bb)->out.vars)); + oldinsz + = htab_elements (shared_hash_htab (VTI (bb)->in.vars)); + oldoutsz + = htab_elements (shared_hash_htab (VTI (bb)->out.vars)); } else oldinsz = oldoutsz = 0; if (MAY_HAVE_DEBUG_INSNS) { - dataflow_set *in = &VTI (bb)->in; - dataflow_set oin, *oldinp = NULL; + dataflow_set *in = &VTI (bb)->in, *first_out = NULL; bool first = true, adjust = false; /* Calculate the IN set as the intersection of predecessor OUT sets. */ - if ((dump_flags & TDF_DETAILS)) - { - oldinp = &oin; - *oldinp = *in; - dataflow_set_init (in, - in->vars ? - htab_elements (in->vars) - : 3); - } - else - dataflow_set_clear (in); + dataflow_set_clear (in); + dst_can_be_shared = true; FOR_EACH_EDGE (e, ei, bb->preds) if (!VTI (e->src)->flooded) @@ -5091,6 +5307,7 @@ vt_find_locations (void) else if (first) { dataflow_set_copy (in, &VTI (e->src)->out); + first_out = &VTI (e->src)->out; first = false; } else @@ -5105,35 +5322,18 @@ vt_find_locations (void) #if ENABLE_CHECKING /* Merge and merge_adjust should keep entries in canonical order. */ - htab_traverse (in->vars, + htab_traverse (shared_hash_htab (in->vars), canonicalize_loc_order_check, in); #endif - } - - VTI (bb)->flooded = true; - - if (oldinp && dump_file && (dump_flags & TDF_DETAILS) - && dataflow_set_different (oldinp, in)) - { - fprintf (dump_file, - "BB %i IN differences above, from", bb->index); - FOR_EACH_EDGE (e, ei, bb->preds) - fprintf (dump_file, " %i", e->src->index); - fputc ('\n', dump_file); - -#if 0 - FOR_EACH_EDGE (e, ei, bb->preds) + if (dst_can_be_shared) { - fprintf (dump_file, "\nBB %i OUT -> %i:\n", - e->src->index, bb->index); - dump_dataflow_set (&VTI (e->src)->out); + shared_hash_destroy (in->vars); + in->vars = shared_hash_copy (first_out->vars); } -#endif } - if (oldinp) - dataflow_set_destroy (oldinp); + VTI (bb)->flooded = true; } else { @@ -5144,7 +5344,9 @@ vt_find_locations (void) } changed = compute_bb_dataflow (bb); - htabsz += VTI (bb)->in.vars->size + VTI (bb)->out.vars->size; + if (dump_file) + htabsz += htab_size (shared_hash_htab (VTI (bb)->in.vars)) + + htab_size (shared_hash_htab (VTI (bb)->out.vars)); if (changed) { @@ -5178,8 +5380,10 @@ vt_find_locations (void) fprintf (dump_file, "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n", bb->index, - (int)VTI (bb)->in.vars->n_elements, oldinsz, - (int)VTI (bb)->out.vars->n_elements, oldoutsz, + (int)htab_elements (shared_hash_htab (VTI (bb)->in.vars)), + oldinsz, + (int)htab_elements (shared_hash_htab (VTI (bb)->out.vars)), + oldoutsz, (int)worklist->nodes, (int)pending->nodes, htabsz); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -5305,7 +5509,7 @@ dump_dataflow_set (dataflow_set *set) dump_attrs_list (set->regs[i]); } } - dump_vars (set->vars); + dump_vars (shared_hash_htab (set->vars)); fprintf (dump_file, "\n"); } @@ -5327,10 +5531,10 @@ dump_dataflow_sets (void) } /* Add variable VAR to the hash table of changed variables and - if it has no locations delete it from hash table HTAB. */ + if it has no locations delete it from SET's hash table. */ static void -variable_was_changed (variable var, htab_t htab) +variable_was_changed (variable var, dataflow_set *set) { hashval_t hash = dv_htab_hash (var->dv); @@ -5342,39 +5546,42 @@ variable_was_changed (variable var, htab set_dv_changed (var->dv, true); slot = htab_find_slot_with_hash (changed_variables, - &var->dv, + var->dv, hash, INSERT); - if (htab && var->n_var_parts == 0) + if (set && var->n_var_parts == 0) { variable empty_var; - void **old; empty_var = (variable) pool_alloc (dv_pool (var->dv)); empty_var->dv = var->dv; - empty_var->refcount = 0; + empty_var->refcount = 1; empty_var->n_var_parts = 0; *slot = empty_var; - - old = htab_find_slot_with_hash (htab, &var->dv, hash, - NO_INSERT); - if (old) - htab_clear_slot (htab, old); + goto drop_var; } else { + var->refcount++; *slot = var; } } else { - gcc_assert (htab); + gcc_assert (set); if (var->n_var_parts == 0) { - void **slot = htab_find_slot_with_hash (htab, &var->dv, - hash, NO_INSERT); + void **slot; + + drop_var: + slot = shared_hash_find_slot_noinsert (set->vars, var->dv); if (slot) - htab_clear_slot (htab, slot); + { + if (shared_hash_shared (set->vars)) + slot = shared_hash_find_slot_unshare (&set->vars, var->dv, + NO_INSERT); + htab_clear_slot (shared_hash_htab (set->vars), slot); + } } } } @@ -5422,7 +5629,7 @@ set_slot_part (dataflow_set *set, rtx lo location_chain *nextp; variable var; bool onepart = dv_onepart_p (dv); - + gcc_assert (offset == 0 || !onepart); gcc_assert (loc != dv_as_opaque (dv)); @@ -5460,9 +5667,9 @@ set_slot_part (dataflow_set *set, rtx lo if (r == 0) return; - if (var->refcount > 1) + if (var->refcount > 1 || shared_hash_shared (set->vars)) { - var = unshare_variable (slot, var, initialized); + var = unshare_variable (set, slot, var, initialized); for (nextp = &var->var_part[0].loc_chain; c; nextp = &(*nextp)->next) c--; @@ -5493,14 +5700,13 @@ set_slot_part (dataflow_set *set, rtx lo if (set_src != NULL) node->set_src = set_src; - *slot = var; return; } else { /* We have to make a copy of a shared variable. */ - if (var->refcount > 1) - var = unshare_variable (slot, var, initialized); + if (var->refcount > 1 || shared_hash_shared (set->vars)) + var = unshare_variable (set, slot, var, initialized); } } else @@ -5508,8 +5714,8 @@ set_slot_part (dataflow_set *set, rtx lo /* We have not found the location part, new one will be created. */ /* We have to make a copy of the shared variable. */ - if (var->refcount > 1) - var = unshare_variable (slot, var, initialized); + if (var->refcount > 1 || shared_hash_shared (set->vars)) + var = unshare_variable (set, slot, var, initialized); /* We track only variables whose size is <= MAX_VAR_PARTS bytes thus there are at most MAX_VAR_PARTS different offsets. */ @@ -5565,7 +5771,7 @@ set_slot_part (dataflow_set *set, rtx lo if (var->var_part[pos].cur_loc == NULL) { var->var_part[pos].cur_loc = loc; - variable_was_changed (var, set->vars); + variable_was_changed (var, set); } } @@ -5581,8 +5787,16 @@ set_variable_part (dataflow_set *set, rt enum var_init_status initialized, rtx set_src, enum insert_option iopt) { - void **slot = htab_find_slot_with_hash (set->vars, &dv, - dv_htab_hash (dv), iopt); + void **slot; + + if (iopt == NO_INSERT) + slot = shared_hash_find_slot_noinsert (set->vars, dv); + else + { + slot = shared_hash_find_slot (set->vars, dv); + if (!slot) + slot = shared_hash_find_slot_unshare (&set->vars, dv, iopt); + } set_slot_part (set, loc, slot, dv, offset, initialized, set_src); } @@ -5658,8 +5872,7 @@ clobber_variable_part (dataflow_set *set || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv)))) return; - slot = htab_find_slot_with_hash (set->vars, &dv, - dv_htab_hash (dv), NO_INSERT); + slot = shared_hash_find_slot_noinsert (set->vars, dv); if (!slot) return; @@ -5682,7 +5895,7 @@ delete_slot_part (dataflow_set *set, rtx location_chain *nextp; bool changed; - if (var->refcount > 1) + if (var->refcount > 1 || shared_hash_shared (set->vars)) { /* If the variable contains the location part we have to make a copy of the variable. */ @@ -5696,7 +5909,7 @@ delete_slot_part (dataflow_set *set, rtx enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; if (! flag_var_tracking_uninit) status = VAR_INIT_STATUS_INITIALIZED; - var = unshare_variable (slot, var, status); + var = unshare_variable (set, slot, var, status); break; } } @@ -5746,7 +5959,7 @@ delete_slot_part (dataflow_set *set, rtx } } if (changed) - variable_was_changed (var, set->vars); + variable_was_changed (var, set); } } @@ -5758,10 +5971,7 @@ static void delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, HOST_WIDE_INT offset) { - void **slot; - - slot = htab_find_slot_with_hash (set->vars, &dv, - dv_htab_hash (dv), NO_INSERT); + void **slot = shared_hash_find_slot_noinsert (set->vars, dv); if (!slot) return; @@ -5776,7 +5986,6 @@ vt_expand_loc_callback (rtx x, bitmap re { htab_t vars = (htab_t)data; decl_or_value dv; - void **slot; variable var; location_chain loc; rtx result; @@ -5787,13 +5996,11 @@ vt_expand_loc_callback (rtx x, bitmap re return NULL; dv = dv_from_value (x); - slot = htab_find_slot_with_hash (vars, &dv, dv_htab_hash (dv), NO_INSERT); + var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv)); - if (!slot) + if (!var) return NULL; - var = (variable)*slot; - if (var->n_var_parts == 0) return NULL; @@ -6005,14 +6212,6 @@ emit_note_insn_var_location (void **varp set_dv_changed (var->dv, false); htab_clear_slot (changed_variables, varp); - /* When there are no location parts the variable has been already - removed from hash table and a new empty variable was created. - Free the empty variable. */ - if (var->n_var_parts == 0 && var->refcount == 0) - { - pool_free (dv_pool (var->dv), var); - } - /* Continue traversing the hash table. */ return 1; } @@ -6085,9 +6284,11 @@ check_changed_var (void **slot, void *da shall be emitted before of after instruction INSN. */ static void -emit_notes_for_changes (rtx insn, enum emit_note_where where, htab_t vars) +emit_notes_for_changes (rtx insn, enum emit_note_where where, + shared_hash vars) { emit_note_data data; + htab_t htab = shared_hash_htab (vars); if (MAY_HAVE_DEBUG_INSNS) { @@ -6100,14 +6301,14 @@ emit_notes_for_changes (rtx insn, enum e do { more_changed = false; - htab_traverse (vars, check_changed_var, &more_changed); + htab_traverse (htab, check_changed_var, &more_changed); } while (more_changed); } data.insn = insn; data.where = where; - data.vars = vars; + data.vars = htab; htab_traverse (changed_variables, emit_note_insn_var_location, &data); } @@ -6121,7 +6322,7 @@ emit_notes_for_differences_1 (void **slo variable old_var, new_var; old_var = (variable) *slot; - new_var = (variable) htab_find_with_hash (new_vars, &old_var->dv, + new_var = (variable) htab_find_with_hash (new_vars, old_var->dv, dv_htab_hash (old_var->dv)); if (!new_var) @@ -6131,7 +6332,7 @@ emit_notes_for_differences_1 (void **slo empty_var = (variable) pool_alloc (dv_pool (old_var->dv)); empty_var->dv = old_var->dv; - empty_var->refcount = 1; + empty_var->refcount = 0; empty_var->n_var_parts = 0; variable_was_changed (empty_var, NULL); } @@ -6154,7 +6355,7 @@ emit_notes_for_differences_2 (void **slo variable old_var, new_var; new_var = (variable) *slot; - old_var = (variable) htab_find_with_hash (old_vars, &new_var->dv, + old_var = (variable) htab_find_with_hash (old_vars, new_var->dv, dv_htab_hash (new_var->dv)); if (!old_var) { @@ -6173,8 +6374,12 @@ static void emit_notes_for_differences (rtx insn, dataflow_set *old_set, dataflow_set *new_set) { - htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars); - htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars); + htab_traverse (shared_hash_htab (old_set->vars), + emit_notes_for_differences_1, + shared_hash_htab (new_set->vars)); + htab_traverse (shared_hash_htab (new_set->vars), + emit_notes_for_differences_2, + shared_hash_htab (old_set->vars)); emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars); } @@ -6186,7 +6391,7 @@ emit_notes_in_bb (basic_block bb) int i; dataflow_set set; - dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3); + dataflow_set_init (&set); dataflow_set_copy (&set, &VTI (bb)->in); for (i = 0; i < VTI (bb)->n_mos; i++) @@ -6461,7 +6666,7 @@ vt_emit_notes (void) delete_variable_part). */ emit_notes = true; - dataflow_set_init (&empty, 7); + dataflow_set_init (&empty); last_out = ∅ FOR_EACH_BB (bb) @@ -6772,18 +6977,6 @@ vt_initialize (void) } } - /* Init the IN and OUT sets. */ - FOR_ALL_BB (bb) - { - VTI (bb)->visited = false; - VTI (bb)->flooded = false; - dataflow_set_init (&VTI (bb)->in, 7); - dataflow_set_init (&VTI (bb)->out, 7); - VTI (bb)->permp = NULL; - } - - VTI (ENTRY_BLOCK_PTR)->flooded = true; - attrs_pool = create_alloc_pool ("attrs_def pool", sizeof (struct attrs_def), 1024); var_pool = create_alloc_pool ("variable_def pool", @@ -6793,8 +6986,27 @@ vt_initialize (void) loc_chain_pool = create_alloc_pool ("location_chain_def pool", sizeof (struct location_chain_def), 1024); + shared_hash_pool = create_alloc_pool ("shared_hash_def pool", + sizeof (struct shared_hash_def), 256); + empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool); + empty_shared_hash->refcount = 1; + empty_shared_hash->htab + = htab_create (1, variable_htab_hash, variable_htab_eq, + variable_htab_free); changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, - NULL); + variable_htab_free); + + /* Init the IN and OUT sets. */ + FOR_ALL_BB (bb) + { + VTI (bb)->visited = false; + VTI (bb)->flooded = false; + dataflow_set_init (&VTI (bb)->in); + dataflow_set_init (&VTI (bb)->out); + VTI (bb)->permp = NULL; + } + + VTI (ENTRY_BLOCK_PTR)->flooded = true; vt_add_function_parameters (); } @@ -6853,10 +7065,12 @@ vt_finalize (void) } } free_aux_for_blocks (); + htab_delete (empty_shared_hash->htab); + htab_delete (changed_variables); free_alloc_pool (attrs_pool); free_alloc_pool (var_pool); free_alloc_pool (loc_chain_pool); - htab_delete (changed_variables); + free_alloc_pool (shared_hash_pool); if (MAY_HAVE_DEBUG_INSNS) { Jakub
Attachment:
P2-checking
Description: Text document
Attachment:
XX
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |