the locations of the entries with the rtx we are looking up. */
/* A table that enables us to look up elts by their value. */
-static htab_t hash_table;
+static htab_t cselib_hash_table;
/* This is a global so we don't have to pass this through every function.
It is used in new_elt_loc_list to set SETTING_INSN. */
n_used_regs = 0;
- htab_empty (hash_table);
+ htab_empty (cselib_hash_table);
n_useless_values = 0;
if (v->locs == 0)
{
CSELIB_VAL_PTR (v->u.val_rtx) = NULL;
- htab_clear_slot (hash_table, x);
+ htab_clear_slot (cselib_hash_table, x);
unchain_one_value (v);
n_useless_values--;
}
do
{
values_became_useless = 0;
- htab_traverse (hash_table, discard_useless_locs, 0);
+ htab_traverse (cselib_hash_table, discard_useless_locs, 0);
}
while (values_became_useless);
}
*p = &dummy_val;
- htab_traverse (hash_table, discard_useless_values, 0);
+ htab_traverse (cselib_hash_table, discard_useless_values, 0);
gcc_assert (!n_useless_values);
}
/* Assume there is only one rtx object for any given label. */
case LABEL_REF:
- hash
- += ((unsigned) LABEL_REF << 7) + (unsigned long) XEXP (x, 0);
+ /* We don't hash on the address of the CODE_LABEL to avoid bootstrap
+ differences and differences between each stage's debugging dumps. */
+ hash += (((unsigned int) LABEL_REF << 7)
+ + CODE_LABEL_NUMBER (XEXP (x, 0)));
return hash ? hash : (unsigned int) LABEL_REF;
case SYMBOL_REF:
- hash
- += ((unsigned) SYMBOL_REF << 7) + (unsigned long) XSTR (x, 0);
- return hash ? hash : (unsigned int) SYMBOL_REF;
+ {
+ /* Don't hash on the symbol's address to avoid bootstrap differences.
+ Different hash values may cause expressions to be recorded in
+ different orders and thus different registers to be used in the
+ final assembler. This also avoids differences in the dump files
+ between various stages. */
+ unsigned int h = 0;
+ const unsigned char *p = (const unsigned char *) XSTR (x, 0);
+
+ while (*p)
+ h += (h << 7) + *p++; /* ??? revisit */
+
+ hash += ((unsigned int) SYMBOL_REF << 7) + h;
+ return hash ? hash : (unsigned int) SYMBOL_REF;
+ }
case PRE_DEC:
case PRE_INC:
mem_elt = new_cselib_val (++next_unknown_value, mode);
add_mem_for_addr (addr, mem_elt, x);
- slot = htab_find_slot_with_hash (hash_table, wrap_constant (mode, x),
+ slot = htab_find_slot_with_hash (cselib_hash_table, wrap_constant (mode, x),
mem_elt->value, INSERT);
*slot = mem_elt;
return mem_elt;
REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL);
}
REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e);
- slot = htab_find_slot_with_hash (hash_table, x, e->value, INSERT);
+ slot = htab_find_slot_with_hash (cselib_hash_table, x, e->value, INSERT);
*slot = e;
return e;
}
if (! hashval)
return 0;
- slot = htab_find_slot_with_hash (hash_table, wrap_constant (mode, x),
+ slot = htab_find_slot_with_hash (cselib_hash_table, wrap_constant (mode, x),
hashval, create ? INSERT : NO_INSERT);
if (slot == 0)
return 0;
cselib_current_insn_in_libcall = false;
cselib_current_insn = 0;
- if (n_useless_values > MAX_USELESS_VALUES)
+ if (n_useless_values > MAX_USELESS_VALUES
+ /* remove_useless_values is linear in the hash table size. Avoid
+ quadratic behaviour for very large hashtables with very few
+ useless elements. */
+ && (unsigned int)n_useless_values > cselib_hash_table->n_elements / 4)
remove_useless_values ();
}
sizeof (struct elt_loc_list), 10);
cselib_val_pool = create_alloc_pool ("cselib_val_list",
sizeof (cselib_val), 10);
- value_pool = create_alloc_pool ("value",
- RTX_SIZE (VALUE), 100);
+ value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100);
cselib_record_memory = record_memory;
/* This is only created once. */
if (! callmem)
/* Some space for newly emit instructions so we don't end up
reallocating in between passes. */
reg_values_size = cselib_nregs + (63 + cselib_nregs) / 16;
- reg_values = xcalloc (reg_values_size, sizeof (reg_values));
+ reg_values = XCNEWVEC (struct elt_list *, reg_values_size);
}
- used_regs = xmalloc (sizeof (*used_regs) * cselib_nregs);
+ used_regs = XNEWVEC (unsigned int, cselib_nregs);
n_used_regs = 0;
- hash_table = htab_create (31, get_value_hash, entry_and_rtx_equal_p, NULL);
+ cselib_hash_table = htab_create (31, get_value_hash,
+ entry_and_rtx_equal_p, NULL);
cselib_current_insn_in_libcall = false;
}
free_alloc_pool (cselib_val_pool);
free_alloc_pool (value_pool);
cselib_clear_table ();
- htab_delete (hash_table);
+ htab_delete (cselib_hash_table);
free (used_regs);
used_regs = 0;
- hash_table = 0;
+ cselib_hash_table = 0;
n_useless_values = 0;
next_unknown_value = 0;
}