This patch extracts approved portions of the hash_table patches to the...
This patch extracts approved portions of the hash_table patches to the cxx-conversion branch for files not under gcc/config. Update various hash tables from htab_t to hash_table. Modify types and calls to match. * tree-ssa-coalesce.c'coalesce_list_d.list from htab_t to hash_table. Fold coalesce_pair_map_hash and coalesce_pair_map_eq into new struct coalesce_pair_hasher. Removed struct coalesce_pair_iterator, as did not meet the hash_table iterator interface and it provided no significant code reduction. This leads to a change in the implementation of FOR_EACH_PARTITION_PAIR. * statistics.c'statistics_hashes Fold hash_statistics_eq into new struct stats_counter_hasher. * hash-table.h'hash_table Add documentation. Add nested class iterator and methods to hash_table. Add FOR_EACH_HASH_TABLE_ELEMENT implemented with those iterators. Change uses of FOR_EACH_HTAB_ELEMENT to FOR_EACH_HASH_TABLE_ELEMENT. * tree-ssa-sccvn.c'vn_tables_s.nary Fold vn_nary_op_hash, vn_nary_op_eq into new struct vn_nary_op_hasher. Add typedef vn_nary_op_table_type. Add typedef vn_nary_op_iterator_type. * tree-ssa-sccvn.c'vn_tables_s.phis Fold vn_phi_hash, free_phi into new struct vn_phi_hasher. Add typedef vn_phi_table_type. Add typedef vn_phi_iterator_type. * tree-ssa-sccvn.c'vn_tables_s.references Fold vn_reference_hash, vn_reference_op_eq, free_reference into new struct vn_reference_hasher. Add typedef vn_reference_table_type. Add typedef vn_reference_iterator_type. * tree-ssa-sccvn.c'constant_value_ids Fold vn_constant_hash, vn_constant_eq into new struct vn_constant_hasher. * tree-into-ssa.c'var_infos Fold var_info_hash, var_info_eq into new struct var_info_hasher. * tree-vectorizer.h'_loop_vec_info::peeling_htab * tree-vectorizer.h New struct peel_info_hasher. * tree-vect-loop.c Update dependent calls and types to match. * tree-vect-data-refs.c Fold vect_peeling_hash and vect_peeling_hash_eq into struct peel_info_hasher. * tree-ssa-reassoc.c'undistribute_ops_list::ctable Fold oecount_hash and oecount_eq into new struct oecount_hasher. * tree-ssa-loop-im.c'memory_accesses.refs Fold memref_hash and memref_eq into new struct mem_ref_hasher. Tested on x86_64. Index: gcc/ChangeLog 2013-04-23 Lawrence Crowl <crowl@google.com> * Makefile.in: Update as needed below. * hash-table.h (class hash_table): Correct many methods with parameter types compare_type to the correct value_type. (Correct code was unlikely to notice the change.) (hash_table::elements_with_deleted) New. (class hashtable::iterator): New. (hashtable::begin()): New. (hashtable::end()): New. (FOR_EACH_HASH_TABLE_ELEMENT): New. * statistics.c (statistics_hashes): Change type to hash_table. Update dependent calls and types. * tree-into-ssa.c (var_infos): Change type to hash_table. Update dependent calls and types. * tree-ssa-coalesce.c (struct coalesce_list_d.list): Change type to hash_table. Update dependent calls and types. * tree-ssa-loop-im.c (struct mem_ref.refs): Change type to hash_table. Update dependent calls and types. * tree-ssa-reassoc.c (undistribute_ops_list::ctable): Change type to hash_table. Update dependent calls and types. * tree-ssa-sccvn.c (vn_tables_s::nary): Change type to hash_table. Update dependent calls and types. (vn_tables_s::phis): Likewise. (vn_tables_s::references): Likewise. * tree-ssa-sccvn.h (vn_nary_op_eq): Update parameter and return types. (vn_reference_eq): Update parameter and return types. * tree-ssa-structalias.c (pointer_equiv_class_table): Change type to hash_table. Update dependent calls and types. (location_equiv_class_table): Likewise. * tree-vect-data-refs.c: Consequential changes for making peeling a hash_table. * tree-vect-loop.c (new_loop_vec_info): Dependent hash_table update. (destroy_loop_vec_info): Dependent hash_table update. * tree-vectorizer.h (peeling_htab): Change type to hash_table. Update dependent calls and types. From-SVN: r198213
This commit is contained in:
parent
4a8043c4e0
commit
bf190e8df2
|
@ -1,3 +1,52 @@
|
|||
2013-04-23 Lawrence Crowl <crowl@google.com>
|
||||
|
||||
* Makefile.in: Update as needed below.
|
||||
|
||||
* hash-table.h (class hash_table):
|
||||
Correct many methods with parameter types compare_type to the correct
|
||||
value_type. (Correct code was unlikely to notice the change.)
|
||||
(hash_table::elements_with_deleted) New.
|
||||
(class hashtable::iterator): New.
|
||||
(hashtable::begin()): New.
|
||||
(hashtable::end()): New.
|
||||
(FOR_EACH_HASH_TABLE_ELEMENT): New.
|
||||
|
||||
* statistics.c (statistics_hashes):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
|
||||
* tree-into-ssa.c (var_infos):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
|
||||
* tree-ssa-coalesce.c (struct coalesce_list_d.list):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
|
||||
* tree-ssa-loop-im.c (struct mem_ref.refs):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
|
||||
* tree-ssa-reassoc.c (undistribute_ops_list::ctable):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
|
||||
* tree-ssa-sccvn.c (vn_tables_s::nary):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
(vn_tables_s::phis): Likewise.
|
||||
(vn_tables_s::references): Likewise.
|
||||
|
||||
* tree-ssa-sccvn.h (vn_nary_op_eq): Update parameter and return types.
|
||||
(vn_reference_eq): Update parameter and return types.
|
||||
|
||||
* tree-ssa-structalias.c (pointer_equiv_class_table):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
(location_equiv_class_table): Likewise.
|
||||
|
||||
* tree-vect-data-refs.c: Consequential changes for making
|
||||
peeling a hash_table.
|
||||
|
||||
* tree-vect-loop.c (new_loop_vec_info): Dependent hash_table update.
|
||||
(destroy_loop_vec_info): Dependent hash_table update.
|
||||
|
||||
* tree-vectorizer.h (peeling_htab):
|
||||
Change type to hash_table. Update dependent calls and types.
|
||||
|
||||
2013-04-23 Shiva Chen <shiva0217@gmail.com>
|
||||
|
||||
* lra-assigns.c (find_hard_regno_for): Use lra_reg_val_equal_p
|
||||
|
|
|
@ -966,7 +966,8 @@ GIMPLE_STREAMER_H = gimple-streamer.h $(LTO_STREAMER_H) $(BASIC_BLOCK_H) \
|
|||
TREE_STREAMER_H = tree-streamer.h $(TREE_H) $(LTO_STREAMER_H) \
|
||||
$(STREAMER_HOOKS_H)
|
||||
STREAMER_HOOKS_H = streamer-hooks.h $(TREE_H)
|
||||
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) $(TARGET_H)
|
||||
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) $(TARGET_H) \
|
||||
$(HASH_TABLE_H)
|
||||
IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
|
||||
IPA_INLINE_H = ipa-inline.h $(IPA_PROP_H)
|
||||
GSTAB_H = gstab.h stab.def
|
||||
|
@ -2255,7 +2256,7 @@ tree-ssa-structalias.o: tree-ssa-structalias.c \
|
|||
$(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(GGC_H) $(OBSTACK_H) $(BITMAP_H) \
|
||||
$(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \
|
||||
$(DIAGNOSTIC_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) \
|
||||
$(GIMPLE_H) $(HASHTAB_H) $(FUNCTION_H) $(CGRAPH_H) \
|
||||
$(GIMPLE_H) $(HASH_TABLE_H) $(FUNCTION_H) $(CGRAPH_H) \
|
||||
$(TREE_PASS_H) alloc-pool.h $(SPLAY_TREE_H) $(PARAMS_H) \
|
||||
$(CGRAPH_H) $(ALIAS_H) pointer-set.h
|
||||
tree-ssa-uninit.o : tree-ssa-uninit.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
||||
|
@ -2275,7 +2276,7 @@ tree-into-ssa.o : tree-into-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
|||
$(TREE_H) $(TM_P_H) $(DIAGNOSTIC_CORE_H) \
|
||||
$(FUNCTION_H) $(TM_H) coretypes.h \
|
||||
langhooks.h domwalk.h $(TREE_PASS_H) $(PARAMS_H) $(BASIC_BLOCK_H) \
|
||||
$(BITMAP_H) $(CFGLOOP_H) $(FLAGS_H) $(HASHTAB_H) \
|
||||
$(BITMAP_H) $(CFGLOOP_H) $(FLAGS_H) $(HASH_TABLE_H) \
|
||||
$(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
|
||||
tree-ssa-ter.o : tree-ssa-ter.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
||||
$(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
|
||||
|
@ -2374,7 +2375,7 @@ tree-ssa-pre.o : tree-ssa-pre.c $(TREE_FLOW_H) $(CONFIG_H) \
|
|||
tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
|
||||
$(TM_H) coretypes.h $(DUMPFILE_H) $(FLAGS_H) $(CFGLOOP_H) \
|
||||
alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASHTAB_H) $(GIMPLE_H) \
|
||||
alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASH_TABLE_H) $(GIMPLE_H) \
|
||||
$(TREE_INLINE_H) tree-ssa-propagate.h tree-ssa-sccvn.h \
|
||||
$(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h
|
||||
gimple-ssa-strength-reduction.o : gimple-ssa-strength-reduction.c $(CONFIG_H) \
|
||||
|
@ -2509,7 +2510,7 @@ tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
|||
pointer-set.h alloc-pool.h \
|
||||
$(TREE_PRETTY_PRINT_H)
|
||||
tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
|
||||
$(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(DIAGNOSTIC_H) \
|
||||
$(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) \
|
||||
tree-iterator.h $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_INLINE_H) \
|
||||
$(VEC_H) langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H) \
|
||||
|
@ -2765,7 +2766,7 @@ function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_
|
|||
$(TREE_PASS_H) $(DF_H) $(PARAMS_H) bb-reorder.h \
|
||||
$(COMMON_TARGET_H)
|
||||
statistics.o : statistics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TREE_PASS_H) $(TREE_DUMP_H) $(HASHTAB_H) statistics.h $(FUNCTION_H)
|
||||
$(TREE_PASS_H) $(TREE_DUMP_H) $(HASH_TABLE_H) statistics.h $(FUNCTION_H)
|
||||
stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) $(TM_H) \
|
||||
$(RTL_H) \
|
||||
$(TREE_H) $(FLAGS_H) $(FUNCTION_H) insn-config.h hard-reg-set.h $(EXPR_H) \
|
||||
|
|
207
gcc/hash-table.h
207
gcc/hash-table.h
|
@ -155,6 +155,47 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
hash_table <pointer_hash <whatever_type>> whatever_type_hash_table;
|
||||
|
||||
|
||||
HASH TABLE ITERATORS
|
||||
|
||||
The hash table provides standard C++ iterators. For example, consider a
|
||||
hash table of some_info. We wish to consume each element of the table:
|
||||
|
||||
extern void consume (some_info *);
|
||||
|
||||
We define a convenience typedef and the hash table:
|
||||
|
||||
typedef hash_table <some_info_hasher> info_table_type;
|
||||
info_table_type info_table;
|
||||
|
||||
Then we write the loop in typical C++ style:
|
||||
|
||||
for (info_table_type::iterator iter = info_table.begin ();
|
||||
iter != info_table.end ();
|
||||
++iter)
|
||||
if ((*iter).status == INFO_READY)
|
||||
consume (&*iter);
|
||||
|
||||
Or with common sub-expression elimination:
|
||||
|
||||
for (info_table_type::iterator iter = info_table.begin ();
|
||||
iter != info_table.end ();
|
||||
++iter)
|
||||
{
|
||||
some_info &elem = *iter;
|
||||
if (elem.status == INFO_READY)
|
||||
consume (&elem);
|
||||
}
|
||||
|
||||
One can also use a more typical GCC style:
|
||||
|
||||
typedef some_info *some_info_p;
|
||||
some_info *elem_ptr;
|
||||
info_table_type::iterator iter;
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (info_table, elem_ptr, some_info_p, iter)
|
||||
if (elem_ptr->status == INFO_READY)
|
||||
consume (elem_ptr);
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
@ -368,6 +409,20 @@ public:
|
|||
typedef typename Descriptor::value_type value_type;
|
||||
typedef typename Descriptor::compare_type compare_type;
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
inline iterator ();
|
||||
inline iterator (value_type **, value_type **);
|
||||
inline value_type &operator * ();
|
||||
void slide ();
|
||||
inline iterator &operator ++ ();
|
||||
inline bool operator != (const iterator &) const;
|
||||
private:
|
||||
value_type **slot_;
|
||||
value_type **limit_;
|
||||
};
|
||||
|
||||
private:
|
||||
hash_table_control <value_type> *htab;
|
||||
|
||||
|
@ -379,19 +434,19 @@ public:
|
|||
void create (size_t initial_slots);
|
||||
bool is_created ();
|
||||
void dispose ();
|
||||
value_type *find (const compare_type *comparable);
|
||||
value_type *find (const value_type *value);
|
||||
value_type *find_with_hash (const compare_type *comparable, hashval_t hash);
|
||||
value_type **find_slot (const compare_type *comparable,
|
||||
enum insert_option insert);
|
||||
value_type **find_slot (const value_type *value, enum insert_option insert);
|
||||
value_type **find_slot_with_hash (const compare_type *comparable,
|
||||
hashval_t hash, enum insert_option insert);
|
||||
void empty ();
|
||||
void clear_slot (value_type **slot);
|
||||
void remove_elt (const compare_type *comparable);
|
||||
void remove_elt (const value_type *value);
|
||||
void remove_elt_with_hash (const compare_type *comparable, hashval_t hash);
|
||||
size_t size();
|
||||
size_t elements();
|
||||
double collisions();
|
||||
size_t size ();
|
||||
size_t elements ();
|
||||
size_t elements_with_deleted ();
|
||||
double collisions ();
|
||||
|
||||
template <typename Argument,
|
||||
int (*Callback) (value_type **slot, Argument argument)>
|
||||
|
@ -400,6 +455,9 @@ public:
|
|||
template <typename Argument,
|
||||
int (*Callback) (value_type **slot, Argument argument)>
|
||||
void traverse (Argument argument);
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
};
|
||||
|
||||
|
||||
|
@ -430,9 +488,9 @@ hash_table <Descriptor, Allocator>::is_created ()
|
|||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline typename Descriptor::value_type *
|
||||
hash_table <Descriptor, Allocator>::find (const compare_type *comparable)
|
||||
hash_table <Descriptor, Allocator>::find (const value_type *value)
|
||||
{
|
||||
return find_with_hash (comparable, Descriptor::hash (comparable));
|
||||
return find_with_hash (value, Descriptor::hash (value));
|
||||
}
|
||||
|
||||
|
||||
|
@ -442,9 +500,9 @@ template <typename Descriptor,
|
|||
template <typename Type> class Allocator>
|
||||
inline typename Descriptor::value_type **
|
||||
hash_table <Descriptor, Allocator>
|
||||
::find_slot (const compare_type *comparable, enum insert_option insert)
|
||||
::find_slot (const value_type *value, enum insert_option insert)
|
||||
{
|
||||
return find_slot_with_hash (comparable, Descriptor::hash (comparable), insert);
|
||||
return find_slot_with_hash (value, Descriptor::hash (value), insert);
|
||||
}
|
||||
|
||||
|
||||
|
@ -453,9 +511,9 @@ hash_table <Descriptor, Allocator>
|
|||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline void
|
||||
hash_table <Descriptor, Allocator>::remove_elt (const compare_type *comparable)
|
||||
hash_table <Descriptor, Allocator>::remove_elt (const value_type *value)
|
||||
{
|
||||
remove_elt_with_hash (comparable, Descriptor::hash (comparable));
|
||||
remove_elt_with_hash (value, Descriptor::hash (value));
|
||||
}
|
||||
|
||||
|
||||
|
@ -475,12 +533,23 @@ hash_table <Descriptor, Allocator>::size()
|
|||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline size_t
|
||||
hash_table <Descriptor, Allocator>::elements()
|
||||
hash_table <Descriptor, Allocator>::elements ()
|
||||
{
|
||||
return htab->n_elements - htab->n_deleted;
|
||||
}
|
||||
|
||||
|
||||
/* Return the current number of elements in this hash table. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline size_t
|
||||
hash_table <Descriptor, Allocator>::elements_with_deleted ()
|
||||
{
|
||||
return htab->n_elements;
|
||||
}
|
||||
|
||||
|
||||
/* Return the fraction of fixed collisions during all work with given
|
||||
hash table. */
|
||||
|
||||
|
@ -881,4 +950,114 @@ hash_table <Descriptor, Allocator>::traverse (Argument argument)
|
|||
traverse_noresize <Argument, Callback> (argument);
|
||||
}
|
||||
|
||||
|
||||
/* Iterator definitions. */
|
||||
|
||||
/* The default constructor produces the end value. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline
|
||||
hash_table <Descriptor, Allocator>::iterator::iterator ()
|
||||
: slot_ (NULL), limit_ (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/* The parameterized constructor produces the begin value. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline
|
||||
hash_table <Descriptor, Allocator>::iterator::iterator
|
||||
(value_type **slot, value_type **limit)
|
||||
: slot_ (slot), limit_ (limit)
|
||||
{
|
||||
}
|
||||
|
||||
/* Obtain the element. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline typename hash_table <Descriptor, Allocator>::value_type &
|
||||
hash_table <Descriptor, Allocator>::iterator::operator * ()
|
||||
{
|
||||
return **slot_;
|
||||
}
|
||||
|
||||
/* Slide down the iterator slots until an active entry is found. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
void
|
||||
hash_table <Descriptor, Allocator>::iterator::slide ()
|
||||
{
|
||||
for ( ; slot_ < limit_; ++slot_ )
|
||||
{
|
||||
value_type *x = *slot_;
|
||||
if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
|
||||
return;
|
||||
}
|
||||
slot_ = NULL;
|
||||
limit_ = NULL;
|
||||
}
|
||||
|
||||
/* Bump the iterator. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline typename hash_table <Descriptor, Allocator>::iterator &
|
||||
hash_table <Descriptor, Allocator>::iterator::operator ++ ()
|
||||
{
|
||||
++slot_;
|
||||
slide ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Compare iterators. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline bool
|
||||
hash_table <Descriptor, Allocator>::iterator::
|
||||
operator != (const iterator &other) const
|
||||
{
|
||||
return slot_ != other.slot_ || limit_ != other.limit_;
|
||||
}
|
||||
|
||||
/* Hash table iterator producers. */
|
||||
|
||||
/* The beginning of a hash table iteration. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline typename hash_table <Descriptor, Allocator>::iterator
|
||||
hash_table <Descriptor, Allocator>::begin ()
|
||||
{
|
||||
iterator hti (htab->entries, htab->entries + htab->size);
|
||||
hti.slide ();
|
||||
return hti;
|
||||
}
|
||||
|
||||
/* The end of a hash table iteration. */
|
||||
|
||||
template <typename Descriptor,
|
||||
template <typename Type> class Allocator>
|
||||
inline typename hash_table <Descriptor, Allocator>::iterator
|
||||
hash_table <Descriptor, Allocator>::end ()
|
||||
{
|
||||
return iterator ();
|
||||
}
|
||||
|
||||
/* Iterate through the elements of hash_table HTAB,
|
||||
using hash_table <....>::iterator ITER,
|
||||
storing each element in RESULT, which is of type TYPE.
|
||||
|
||||
This macro has this form for compatibility with the
|
||||
FOR_EACH_HTAB_ELEMENT currently defined in tree-flow.h. */
|
||||
|
||||
#define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
|
||||
for ((ITER) = (HTAB).begin (); \
|
||||
(ITER) != (HTAB).end () ? (RESULT = &*(ITER) , true) : false; \
|
||||
++(ITER))
|
||||
|
||||
#endif /* TYPED_HASHTAB_H */
|
||||
|
|
105
gcc/statistics.c
105
gcc/statistics.c
|
@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tree-pass.h"
|
||||
#include "tree-dump.h"
|
||||
#include "statistics.h"
|
||||
#include "hashtab.h"
|
||||
#include "hash-table.h"
|
||||
#include "function.h"
|
||||
|
||||
static int statistics_dump_nr;
|
||||
|
@ -42,42 +42,52 @@ typedef struct statistics_counter_s {
|
|||
unsigned HOST_WIDE_INT prev_dumped_count;
|
||||
} statistics_counter_t;
|
||||
|
||||
/* Array of statistic hashes, indexed by pass id. */
|
||||
static htab_t *statistics_hashes;
|
||||
static unsigned nr_statistics_hashes;
|
||||
/* Hashtable helpers. */
|
||||
|
||||
struct stats_counter_hasher
|
||||
{
|
||||
typedef statistics_counter_t value_type;
|
||||
typedef statistics_counter_t compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
static inline void remove (value_type *);
|
||||
};
|
||||
|
||||
/* Hash a statistic counter by its string ID. */
|
||||
|
||||
static hashval_t
|
||||
hash_statistics_hash (const void *p)
|
||||
inline hashval_t
|
||||
stats_counter_hasher::hash (const value_type *c)
|
||||
{
|
||||
const statistics_counter_t *const c = (const statistics_counter_t *)p;
|
||||
return htab_hash_string (c->id) + c->val;
|
||||
}
|
||||
|
||||
/* Compare two statistic counters by their string IDs. */
|
||||
|
||||
static int
|
||||
hash_statistics_eq (const void *p, const void *q)
|
||||
inline bool
|
||||
stats_counter_hasher::equal (const value_type *c1, const compare_type *c2)
|
||||
{
|
||||
const statistics_counter_t *const c1 = (const statistics_counter_t *)p;
|
||||
const statistics_counter_t *const c2 = (const statistics_counter_t *)q;
|
||||
return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
|
||||
}
|
||||
|
||||
/* Free a statistics entry. */
|
||||
|
||||
static void
|
||||
hash_statistics_free (void *p)
|
||||
inline void
|
||||
stats_counter_hasher::remove (value_type *v)
|
||||
{
|
||||
free (CONST_CAST(char *, ((statistics_counter_t *)p)->id));
|
||||
free (p);
|
||||
free (CONST_CAST(char *, v->id));
|
||||
free (v);
|
||||
}
|
||||
|
||||
typedef hash_table <stats_counter_hasher> stats_counter_table_type;
|
||||
|
||||
/* Array of statistic hashes, indexed by pass id. */
|
||||
static stats_counter_table_type *statistics_hashes;
|
||||
static unsigned nr_statistics_hashes;
|
||||
|
||||
/* Return the current hashtable to be used for recording or printing
|
||||
statistics. */
|
||||
|
||||
static htab_t
|
||||
static stats_counter_table_type
|
||||
curr_statistics_hash (void)
|
||||
{
|
||||
unsigned idx;
|
||||
|
@ -86,20 +96,20 @@ curr_statistics_hash (void)
|
|||
idx = current_pass->static_pass_number;
|
||||
|
||||
if (idx < nr_statistics_hashes
|
||||
&& statistics_hashes[idx] != NULL)
|
||||
&& statistics_hashes[idx].is_created ())
|
||||
return statistics_hashes[idx];
|
||||
|
||||
if (idx >= nr_statistics_hashes)
|
||||
{
|
||||
statistics_hashes = XRESIZEVEC (struct htab *, statistics_hashes, idx+1);
|
||||
statistics_hashes = XRESIZEVEC (stats_counter_table_type,
|
||||
statistics_hashes, idx+1);
|
||||
memset (statistics_hashes + nr_statistics_hashes, 0,
|
||||
(idx + 1 - nr_statistics_hashes) * sizeof (htab_t));
|
||||
(idx + 1 - nr_statistics_hashes)
|
||||
* sizeof (stats_counter_table_type));
|
||||
nr_statistics_hashes = idx + 1;
|
||||
}
|
||||
|
||||
statistics_hashes[idx] = htab_create (15, hash_statistics_hash,
|
||||
hash_statistics_eq,
|
||||
hash_statistics_free);
|
||||
statistics_hashes[idx].create (15);
|
||||
|
||||
return statistics_hashes[idx];
|
||||
}
|
||||
|
@ -107,10 +117,11 @@ curr_statistics_hash (void)
|
|||
/* Helper for statistics_fini_pass. Print the counter difference
|
||||
since the last dump for the pass dump files. */
|
||||
|
||||
static int
|
||||
statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||
int
|
||||
statistics_fini_pass_1 (statistics_counter_t **slot,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
statistics_counter_t *counter = (statistics_counter_t *)*slot;
|
||||
statistics_counter_t *counter = *slot;
|
||||
unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
|
||||
if (count == 0)
|
||||
return 1;
|
||||
|
@ -127,10 +138,11 @@ statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
/* Helper for statistics_fini_pass. Print the counter difference
|
||||
since the last dump for the statistics dump. */
|
||||
|
||||
static int
|
||||
statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||
int
|
||||
statistics_fini_pass_2 (statistics_counter_t **slot,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
statistics_counter_t *counter = (statistics_counter_t *)*slot;
|
||||
statistics_counter_t *counter = *slot;
|
||||
unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
|
||||
if (count == 0)
|
||||
return 1;
|
||||
|
@ -157,10 +169,11 @@ statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
|
||||
/* Helper for statistics_fini_pass, reset the counters. */
|
||||
|
||||
static int
|
||||
statistics_fini_pass_3 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||
int
|
||||
statistics_fini_pass_3 (statistics_counter_t **slot,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
statistics_counter_t *counter = (statistics_counter_t *)*slot;
|
||||
statistics_counter_t *counter = *slot;
|
||||
counter->prev_dumped_count = counter->count;
|
||||
return 1;
|
||||
}
|
||||
|
@ -179,26 +192,25 @@ statistics_fini_pass (void)
|
|||
fprintf (dump_file, "\n");
|
||||
fprintf (dump_file, "Pass statistics:\n");
|
||||
fprintf (dump_file, "----------------\n");
|
||||
htab_traverse_noresize (curr_statistics_hash (),
|
||||
statistics_fini_pass_1, NULL);
|
||||
curr_statistics_hash ()
|
||||
.traverse_noresize <void *, statistics_fini_pass_1> (NULL);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
if (statistics_dump_file
|
||||
&& !(statistics_dump_flags & TDF_STATS
|
||||
|| statistics_dump_flags & TDF_DETAILS))
|
||||
htab_traverse_noresize (curr_statistics_hash (),
|
||||
statistics_fini_pass_2, NULL);
|
||||
htab_traverse_noresize (curr_statistics_hash (),
|
||||
statistics_fini_pass_3, NULL);
|
||||
curr_statistics_hash ()
|
||||
.traverse_noresize <void *, statistics_fini_pass_2> (NULL);
|
||||
curr_statistics_hash ()
|
||||
.traverse_noresize <void *, statistics_fini_pass_3> (NULL);
|
||||
}
|
||||
|
||||
/* Helper for printing summary information. */
|
||||
|
||||
static int
|
||||
statistics_fini_1 (void **slot, void *data)
|
||||
int
|
||||
statistics_fini_1 (statistics_counter_t **slot, opt_pass *pass)
|
||||
{
|
||||
struct opt_pass *pass = (struct opt_pass *)data;
|
||||
statistics_counter_t *counter = (statistics_counter_t *)*slot;
|
||||
statistics_counter_t *counter = *slot;
|
||||
if (counter->count == 0)
|
||||
return 1;
|
||||
if (counter->histogram_p)
|
||||
|
@ -230,10 +242,11 @@ statistics_fini (void)
|
|||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < nr_statistics_hashes; ++i)
|
||||
if (statistics_hashes[i] != NULL
|
||||
if (statistics_hashes[i].is_created ()
|
||||
&& get_pass_for_id (i) != NULL)
|
||||
htab_traverse_noresize (statistics_hashes[i],
|
||||
statistics_fini_1, get_pass_for_id (i));
|
||||
statistics_hashes[i]
|
||||
.traverse_noresize <opt_pass *, statistics_fini_1>
|
||||
(get_pass_for_id (i));
|
||||
}
|
||||
|
||||
dump_end (statistics_dump_nr, statistics_dump_file);
|
||||
|
@ -261,14 +274,14 @@ statistics_init (void)
|
|||
and HISTOGRAM_P. */
|
||||
|
||||
static statistics_counter_t *
|
||||
lookup_or_add_counter (htab_t hash, const char *id, int val,
|
||||
lookup_or_add_counter (stats_counter_table_type hash, const char *id, int val,
|
||||
bool histogram_p)
|
||||
{
|
||||
statistics_counter_t **counter;
|
||||
statistics_counter_t c;
|
||||
c.id = id;
|
||||
c.val = val;
|
||||
counter = (statistics_counter_t **) htab_find_slot (hash, &c, INSERT);
|
||||
counter = hash.find_slot (&c, INSERT);
|
||||
if (!*counter)
|
||||
{
|
||||
*counter = XNEW (struct statistics_counter_s);
|
||||
|
|
|
@ -33,7 +33,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tree-flow.h"
|
||||
#include "gimple.h"
|
||||
#include "tree-inline.h"
|
||||
#include "hashtab.h"
|
||||
#include "hash-table.h"
|
||||
#include "tree-pass.h"
|
||||
#include "cfgloop.h"
|
||||
#include "domwalk.h"
|
||||
|
@ -160,9 +160,32 @@ struct var_info_d
|
|||
typedef struct var_info_d *var_info_p;
|
||||
|
||||
|
||||
/* VAR_INFOS hashtable helpers. */
|
||||
|
||||
struct var_info_hasher : typed_free_remove <var_info_d>
|
||||
{
|
||||
typedef var_info_d value_type;
|
||||
typedef var_info_d compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
inline hashval_t
|
||||
var_info_hasher::hash (const value_type *p)
|
||||
{
|
||||
return DECL_UID (p->var);
|
||||
}
|
||||
|
||||
inline bool
|
||||
var_info_hasher::equal (const value_type *p1, const compare_type *p2)
|
||||
{
|
||||
return p1->var == p2->var;
|
||||
}
|
||||
|
||||
|
||||
/* Each entry in VAR_INFOS contains an element of type STRUCT
|
||||
VAR_INFO_D. */
|
||||
static htab_t var_infos;
|
||||
static hash_table <var_info_hasher> var_infos;
|
||||
|
||||
|
||||
/* Information stored for SSA names. */
|
||||
|
@ -340,17 +363,17 @@ static inline var_info_p
|
|||
get_var_info (tree decl)
|
||||
{
|
||||
struct var_info_d vi;
|
||||
void **slot;
|
||||
var_info_d **slot;
|
||||
vi.var = decl;
|
||||
slot = htab_find_slot_with_hash (var_infos, &vi, DECL_UID (decl), INSERT);
|
||||
slot = var_infos.find_slot_with_hash (&vi, DECL_UID (decl), INSERT);
|
||||
if (*slot == NULL)
|
||||
{
|
||||
var_info_p v = XCNEW (struct var_info_d);
|
||||
v->var = decl;
|
||||
*slot = (void *)v;
|
||||
*slot = v;
|
||||
return v;
|
||||
}
|
||||
return (var_info_p) *slot;
|
||||
return *slot;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1044,15 +1067,15 @@ insert_phi_nodes_compare_var_infos (const void *a, const void *b)
|
|||
static void
|
||||
insert_phi_nodes (bitmap_head *dfs)
|
||||
{
|
||||
htab_iterator hi;
|
||||
hash_table <var_info_hasher>::iterator hi;
|
||||
unsigned i;
|
||||
var_info_p info;
|
||||
vec<var_info_p> vars;
|
||||
|
||||
timevar_push (TV_TREE_INSERT_PHI_NODES);
|
||||
|
||||
vars.create (htab_elements (var_infos));
|
||||
FOR_EACH_HTAB_ELEMENT (var_infos, info, var_info_p, hi)
|
||||
vars.create (var_infos.elements ());
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (var_infos, info, var_info_p, hi)
|
||||
if (info->info.need_phi_state != NEED_PHI_STATE_NO)
|
||||
vars.quick_push (info);
|
||||
|
||||
|
@ -1632,12 +1655,12 @@ debug_tree_ssa (void)
|
|||
/* Dump statistics for the hash table HTAB. */
|
||||
|
||||
static void
|
||||
htab_statistics (FILE *file, htab_t htab)
|
||||
htab_statistics (FILE *file, hash_table <var_info_hasher> htab)
|
||||
{
|
||||
fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n",
|
||||
(long) htab_size (htab),
|
||||
(long) htab_elements (htab),
|
||||
htab_collisions (htab));
|
||||
(long) htab.size (),
|
||||
(long) htab.elements (),
|
||||
htab.collisions ());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1646,7 +1669,7 @@ htab_statistics (FILE *file, htab_t htab)
|
|||
void
|
||||
dump_tree_ssa_stats (FILE *file)
|
||||
{
|
||||
if (var_infos)
|
||||
if (var_infos.is_created ())
|
||||
{
|
||||
fprintf (file, "\nHash table statistics:\n");
|
||||
fprintf (file, " var_infos: ");
|
||||
|
@ -1665,29 +1688,12 @@ debug_tree_ssa_stats (void)
|
|||
}
|
||||
|
||||
|
||||
/* Hashing and equality functions for VAR_INFOS. */
|
||||
|
||||
static hashval_t
|
||||
var_info_hash (const void *p)
|
||||
{
|
||||
return DECL_UID (((const struct var_info_d *)p)->var);
|
||||
}
|
||||
|
||||
static int
|
||||
var_info_eq (const void *p1, const void *p2)
|
||||
{
|
||||
return ((const struct var_info_d *)p1)->var
|
||||
== ((const struct var_info_d *)p2)->var;
|
||||
}
|
||||
|
||||
|
||||
/* Callback for htab_traverse to dump the VAR_INFOS hash table. */
|
||||
|
||||
static int
|
||||
debug_var_infos_r (void **slot, void *data)
|
||||
int
|
||||
debug_var_infos_r (var_info_d **slot, FILE *file)
|
||||
{
|
||||
FILE *file = (FILE *) data;
|
||||
struct var_info_d *info = (struct var_info_d *) *slot;
|
||||
struct var_info_d *info = *slot;
|
||||
|
||||
fprintf (file, "VAR: ");
|
||||
print_generic_expr (file, info->var, dump_flags);
|
||||
|
@ -1708,8 +1714,8 @@ void
|
|||
dump_var_infos (FILE *file)
|
||||
{
|
||||
fprintf (file, "\n\nDefinition and live-in blocks:\n\n");
|
||||
if (var_infos)
|
||||
htab_traverse (var_infos, debug_var_infos_r, file);
|
||||
if (var_infos.is_created ())
|
||||
var_infos.traverse <FILE *, debug_var_infos_r> (file);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2216,7 +2222,7 @@ rewrite_blocks (basic_block entry, enum rewrite_mode what)
|
|||
if (dump_file && (dump_flags & TDF_STATS))
|
||||
{
|
||||
dump_dfa_stats (dump_file);
|
||||
if (var_infos)
|
||||
if (var_infos.is_created ())
|
||||
dump_tree_ssa_stats (dump_file);
|
||||
}
|
||||
|
||||
|
@ -2296,9 +2302,8 @@ init_ssa_renamer (void)
|
|||
cfun->gimple_df->in_ssa_p = false;
|
||||
|
||||
/* Allocate memory for the DEF_BLOCKS hash table. */
|
||||
gcc_assert (var_infos == NULL);
|
||||
var_infos = htab_create (vec_safe_length (cfun->local_decls),
|
||||
var_info_hash, var_info_eq, free);
|
||||
gcc_assert (!var_infos.is_created ());
|
||||
var_infos.create (vec_safe_length (cfun->local_decls));
|
||||
|
||||
bitmap_obstack_initialize (&update_ssa_obstack);
|
||||
}
|
||||
|
@ -2309,11 +2314,8 @@ init_ssa_renamer (void)
|
|||
static void
|
||||
fini_ssa_renamer (void)
|
||||
{
|
||||
if (var_infos)
|
||||
{
|
||||
htab_delete (var_infos);
|
||||
var_infos = NULL;
|
||||
}
|
||||
if (var_infos.is_created ())
|
||||
var_infos.dispose ();
|
||||
|
||||
bitmap_obstack_release (&update_ssa_obstack);
|
||||
|
||||
|
@ -3189,7 +3191,7 @@ update_ssa (unsigned update_flags)
|
|||
{
|
||||
/* If we rename bare symbols initialize the mapping to
|
||||
auxiliar info we need to keep track of. */
|
||||
var_infos = htab_create (47, var_info_hash, var_info_eq, free);
|
||||
var_infos.create (47);
|
||||
|
||||
/* If we have to rename some symbols from scratch, we need to
|
||||
start the process at the root of the CFG. FIXME, it should
|
||||
|
|
|
@ -49,6 +49,41 @@ typedef struct coalesce_pair
|
|||
} * coalesce_pair_p;
|
||||
typedef const struct coalesce_pair *const_coalesce_pair_p;
|
||||
|
||||
/* Coalesce pair hashtable helpers. */
|
||||
|
||||
struct coalesce_pair_hasher : typed_noop_remove <coalesce_pair>
|
||||
{
|
||||
typedef coalesce_pair value_type;
|
||||
typedef coalesce_pair compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* Hash function for coalesce list. Calculate hash for PAIR. */
|
||||
|
||||
inline hashval_t
|
||||
coalesce_pair_hasher::hash (const value_type *pair)
|
||||
{
|
||||
hashval_t a = (hashval_t)(pair->first_element);
|
||||
hashval_t b = (hashval_t)(pair->second_element);
|
||||
|
||||
return b * (b - 1) / 2 + a;
|
||||
}
|
||||
|
||||
/* Equality function for coalesce list hash table. Compare PAIR1 and PAIR2,
|
||||
returning TRUE if the two pairs are equivalent. */
|
||||
|
||||
inline bool
|
||||
coalesce_pair_hasher::equal (const value_type *p1, const compare_type *p2)
|
||||
{
|
||||
return (p1->first_element == p2->first_element
|
||||
&& p1->second_element == p2->second_element);
|
||||
}
|
||||
|
||||
typedef hash_table <coalesce_pair_hasher> coalesce_table_type;
|
||||
typedef coalesce_table_type::iterator coalesce_iterator_type;
|
||||
|
||||
|
||||
typedef struct cost_one_pair_d
|
||||
{
|
||||
int first_element;
|
||||
|
@ -60,7 +95,7 @@ typedef struct cost_one_pair_d
|
|||
|
||||
typedef struct coalesce_list_d
|
||||
{
|
||||
htab_t list; /* Hash table. */
|
||||
coalesce_table_type list; /* Hash table. */
|
||||
coalesce_pair_p *sorted; /* List when sorted. */
|
||||
int num_sorted; /* Number in the sorted list. */
|
||||
cost_one_pair_p cost_one_list;/* Single use coalesces with cost 1. */
|
||||
|
@ -185,34 +220,6 @@ pop_best_coalesce (coalesce_list_p cl, int *p1, int *p2)
|
|||
}
|
||||
|
||||
|
||||
#define COALESCE_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
|
||||
|
||||
/* Hash function for coalesce list. Calculate hash for PAIR. */
|
||||
|
||||
static unsigned int
|
||||
coalesce_pair_map_hash (const void *pair)
|
||||
{
|
||||
hashval_t a = (hashval_t)(((const_coalesce_pair_p)pair)->first_element);
|
||||
hashval_t b = (hashval_t)(((const_coalesce_pair_p)pair)->second_element);
|
||||
|
||||
return COALESCE_HASH_FN (a,b);
|
||||
}
|
||||
|
||||
|
||||
/* Equality function for coalesce list hash table. Compare PAIR1 and PAIR2,
|
||||
returning TRUE if the two pairs are equivalent. */
|
||||
|
||||
static int
|
||||
coalesce_pair_map_eq (const void *pair1, const void *pair2)
|
||||
{
|
||||
const_coalesce_pair_p const p1 = (const_coalesce_pair_p) pair1;
|
||||
const_coalesce_pair_p const p2 = (const_coalesce_pair_p) pair2;
|
||||
|
||||
return (p1->first_element == p2->first_element
|
||||
&& p1->second_element == p2->second_element);
|
||||
}
|
||||
|
||||
|
||||
/* Create a new empty coalesce list object and return it. */
|
||||
|
||||
static inline coalesce_list_p
|
||||
|
@ -225,8 +232,7 @@ create_coalesce_list (void)
|
|||
size = 40;
|
||||
|
||||
list = (coalesce_list_p) xmalloc (sizeof (struct coalesce_list_d));
|
||||
list->list = htab_create (size, coalesce_pair_map_hash,
|
||||
coalesce_pair_map_eq, NULL);
|
||||
list->list.create (size);
|
||||
list->sorted = NULL;
|
||||
list->num_sorted = 0;
|
||||
list->cost_one_list = NULL;
|
||||
|
@ -240,7 +246,7 @@ static inline void
|
|||
delete_coalesce_list (coalesce_list_p cl)
|
||||
{
|
||||
gcc_assert (cl->cost_one_list == NULL);
|
||||
htab_delete (cl->list);
|
||||
cl->list.dispose ();
|
||||
free (cl->sorted);
|
||||
gcc_assert (cl->num_sorted == 0);
|
||||
free (cl);
|
||||
|
@ -255,7 +261,7 @@ static coalesce_pair_p
|
|||
find_coalesce_pair (coalesce_list_p cl, int p1, int p2, bool create)
|
||||
{
|
||||
struct coalesce_pair p;
|
||||
void **slot;
|
||||
coalesce_pair **slot;
|
||||
unsigned int hash;
|
||||
|
||||
/* Normalize so that p1 is the smaller value. */
|
||||
|
@ -270,9 +276,8 @@ find_coalesce_pair (coalesce_list_p cl, int p1, int p2, bool create)
|
|||
p.second_element = p2;
|
||||
}
|
||||
|
||||
hash = coalesce_pair_map_hash (&p);
|
||||
slot = htab_find_slot_with_hash (cl->list, &p, hash,
|
||||
create ? INSERT : NO_INSERT);
|
||||
hash = coalesce_pair_hasher::hash (&p);
|
||||
slot = cl->list.find_slot_with_hash (&p, hash, create ? INSERT : NO_INSERT);
|
||||
if (!slot)
|
||||
return NULL;
|
||||
|
||||
|
@ -283,7 +288,7 @@ find_coalesce_pair (coalesce_list_p cl, int p1, int p2, bool create)
|
|||
pair->first_element = p.first_element;
|
||||
pair->second_element = p.second_element;
|
||||
pair->cost = 0;
|
||||
*slot = (void *)pair;
|
||||
*slot = pair;
|
||||
}
|
||||
|
||||
return (struct coalesce_pair *) *slot;
|
||||
|
@ -355,56 +360,14 @@ compare_pairs (const void *p1, const void *p2)
|
|||
static inline int
|
||||
num_coalesce_pairs (coalesce_list_p cl)
|
||||
{
|
||||
return htab_elements (cl->list);
|
||||
}
|
||||
|
||||
|
||||
/* Iterator over hash table pairs. */
|
||||
typedef struct
|
||||
{
|
||||
htab_iterator hti;
|
||||
} coalesce_pair_iterator;
|
||||
|
||||
|
||||
/* Return first partition pair from list CL, initializing iterator ITER. */
|
||||
|
||||
static inline coalesce_pair_p
|
||||
first_coalesce_pair (coalesce_list_p cl, coalesce_pair_iterator *iter)
|
||||
{
|
||||
coalesce_pair_p pair;
|
||||
|
||||
pair = (coalesce_pair_p) first_htab_element (&(iter->hti), cl->list);
|
||||
return pair;
|
||||
}
|
||||
|
||||
|
||||
/* Return TRUE if there are no more partitions in for ITER to process. */
|
||||
|
||||
static inline bool
|
||||
end_coalesce_pair_p (coalesce_pair_iterator *iter)
|
||||
{
|
||||
return end_htab_p (&(iter->hti));
|
||||
}
|
||||
|
||||
|
||||
/* Return the next partition pair to be visited by ITER. */
|
||||
|
||||
static inline coalesce_pair_p
|
||||
next_coalesce_pair (coalesce_pair_iterator *iter)
|
||||
{
|
||||
coalesce_pair_p pair;
|
||||
|
||||
pair = (coalesce_pair_p) next_htab_element (&(iter->hti));
|
||||
return pair;
|
||||
return cl->list.elements ();
|
||||
}
|
||||
|
||||
|
||||
/* Iterate over CL using ITER, returning values in PAIR. */
|
||||
|
||||
#define FOR_EACH_PARTITION_PAIR(PAIR, ITER, CL) \
|
||||
for ((PAIR) = first_coalesce_pair ((CL), &(ITER)); \
|
||||
!end_coalesce_pair_p (&(ITER)); \
|
||||
(PAIR) = next_coalesce_pair (&(ITER)))
|
||||
FOR_EACH_HASH_TABLE_ELEMENT ((CL)->list, (PAIR), coalesce_pair_p, (ITER))
|
||||
|
||||
|
||||
/* Prepare CL for removal of preferred pairs. When finished they are sorted
|
||||
|
@ -415,7 +378,7 @@ sort_coalesce_list (coalesce_list_p cl)
|
|||
{
|
||||
unsigned x, num;
|
||||
coalesce_pair_p p;
|
||||
coalesce_pair_iterator ppi;
|
||||
coalesce_iterator_type ppi;
|
||||
|
||||
gcc_assert (cl->sorted == NULL);
|
||||
|
||||
|
@ -461,7 +424,8 @@ static void
|
|||
dump_coalesce_list (FILE *f, coalesce_list_p cl)
|
||||
{
|
||||
coalesce_pair_p node;
|
||||
coalesce_pair_iterator ppi;
|
||||
coalesce_iterator_type ppi;
|
||||
|
||||
int x;
|
||||
tree var;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "params.h"
|
||||
#include "tree-pass.h"
|
||||
#include "flags.h"
|
||||
#include "hashtab.h"
|
||||
#include "hash-table.h"
|
||||
#include "tree-affine.h"
|
||||
#include "pointer-set.h"
|
||||
#include "tree-ssa-propagate.h"
|
||||
|
@ -133,6 +133,32 @@ typedef struct mem_ref
|
|||
and its subloops. */
|
||||
#define LOOP_DEP_BIT(loopnum, storedp) (2 * (loopnum) + (storedp ? 1 : 0))
|
||||
|
||||
/* Mem_ref hashtable helpers. */
|
||||
|
||||
struct mem_ref_hasher : typed_noop_remove <mem_ref>
|
||||
{
|
||||
typedef mem_ref value_type;
|
||||
typedef tree_node compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* A hash function for struct mem_ref object OBJ. */
|
||||
|
||||
inline hashval_t
|
||||
mem_ref_hasher::hash (const value_type *mem)
|
||||
{
|
||||
return mem->hash;
|
||||
}
|
||||
|
||||
/* An equality function for struct mem_ref object MEM1 with
|
||||
memory reference OBJ2. */
|
||||
|
||||
inline bool
|
||||
mem_ref_hasher::equal (const value_type *mem1, const compare_type *obj2)
|
||||
{
|
||||
return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Description of memory accesses in loops. */
|
||||
|
@ -140,7 +166,7 @@ typedef struct mem_ref
|
|||
static struct
|
||||
{
|
||||
/* The hash table of memory references accessed in loops. */
|
||||
htab_t refs;
|
||||
hash_table <mem_ref_hasher> refs;
|
||||
|
||||
/* The list of memory references. */
|
||||
vec<mem_ref_p> refs_list;
|
||||
|
@ -646,7 +672,7 @@ mem_ref_in_stmt (gimple stmt)
|
|||
gcc_assert (!store);
|
||||
|
||||
hash = iterative_hash_expr (*mem, 0);
|
||||
ref = (mem_ref_p) htab_find_with_hash (memory_accesses.refs, *mem, hash);
|
||||
ref = memory_accesses.refs.find_with_hash (*mem, hash);
|
||||
|
||||
gcc_assert (ref != NULL);
|
||||
return ref;
|
||||
|
@ -1411,27 +1437,6 @@ force_move_till (tree ref, tree *index, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* A hash function for struct mem_ref object OBJ. */
|
||||
|
||||
static hashval_t
|
||||
memref_hash (const void *obj)
|
||||
{
|
||||
const struct mem_ref *const mem = (const struct mem_ref *) obj;
|
||||
|
||||
return mem->hash;
|
||||
}
|
||||
|
||||
/* An equality function for struct mem_ref object OBJ1 with
|
||||
memory reference OBJ2. */
|
||||
|
||||
static int
|
||||
memref_eq (const void *obj1, const void *obj2)
|
||||
{
|
||||
const struct mem_ref *const mem1 = (const struct mem_ref *) obj1;
|
||||
|
||||
return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0);
|
||||
}
|
||||
|
||||
/* A function to free the mem_ref object OBJ. */
|
||||
|
||||
static void
|
||||
|
@ -1502,7 +1507,7 @@ gather_mem_refs_stmt (struct loop *loop, gimple stmt)
|
|||
{
|
||||
tree *mem = NULL;
|
||||
hashval_t hash;
|
||||
PTR *slot;
|
||||
mem_ref **slot;
|
||||
mem_ref_p ref;
|
||||
bool is_stored;
|
||||
unsigned id;
|
||||
|
@ -1526,8 +1531,7 @@ gather_mem_refs_stmt (struct loop *loop, gimple stmt)
|
|||
else
|
||||
{
|
||||
hash = iterative_hash_expr (*mem, 0);
|
||||
slot = htab_find_slot_with_hash (memory_accesses.refs,
|
||||
*mem, hash, INSERT);
|
||||
slot = memory_accesses.refs.find_slot_with_hash (*mem, hash, INSERT);
|
||||
if (*slot)
|
||||
{
|
||||
ref = (mem_ref_p) *slot;
|
||||
|
@ -2553,7 +2557,7 @@ tree_ssa_lim_initialize (void)
|
|||
|
||||
alloc_aux_for_edges (0);
|
||||
|
||||
memory_accesses.refs = htab_create (100, memref_hash, memref_eq, NULL);
|
||||
memory_accesses.refs.create (100);
|
||||
memory_accesses.refs_list.create (100);
|
||||
/* Allocate a special, unanalyzable mem-ref with ID zero. */
|
||||
memory_accesses.refs_list.quick_push
|
||||
|
@ -2596,7 +2600,7 @@ tree_ssa_lim_finalize (void)
|
|||
bitmap_obstack_release (&lim_bitmap_obstack);
|
||||
pointer_map_destroy (lim_aux_data_map);
|
||||
|
||||
htab_delete (memory_accesses.refs);
|
||||
memory_accesses.refs.dispose ();
|
||||
|
||||
FOR_EACH_VEC_ELT (memory_accesses.refs_list, i, ref)
|
||||
memref_free (ref);
|
||||
|
|
|
@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "hash-table.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "basic-block.h"
|
||||
|
@ -943,10 +944,23 @@ typedef struct oecount_s {
|
|||
/* The heap for the oecount hashtable and the sorted list of operands. */
|
||||
static vec<oecount> cvec;
|
||||
|
||||
|
||||
/* Oecount hashtable helpers. */
|
||||
|
||||
struct oecount_hasher : typed_noop_remove <void>
|
||||
{
|
||||
/* Note that this hash table stores integers, not pointers.
|
||||
So, observe the casting in the member functions. */
|
||||
typedef void value_type;
|
||||
typedef void compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* Hash function for oecount. */
|
||||
|
||||
static hashval_t
|
||||
oecount_hash (const void *p)
|
||||
inline hashval_t
|
||||
oecount_hasher::hash (const value_type *p)
|
||||
{
|
||||
const oecount *c = &cvec[(size_t)p - 42];
|
||||
return htab_hash_pointer (c->op) ^ (hashval_t)c->oecode;
|
||||
|
@ -954,8 +968,8 @@ oecount_hash (const void *p)
|
|||
|
||||
/* Comparison function for oecount. */
|
||||
|
||||
static int
|
||||
oecount_eq (const void *p1, const void *p2)
|
||||
inline bool
|
||||
oecount_hasher::equal (const value_type *p1, const compare_type *p2)
|
||||
{
|
||||
const oecount *c1 = &cvec[(size_t)p1 - 42];
|
||||
const oecount *c2 = &cvec[(size_t)p2 - 42];
|
||||
|
@ -1257,7 +1271,7 @@ undistribute_ops_list (enum tree_code opcode,
|
|||
unsigned nr_candidates, nr_candidates2;
|
||||
sbitmap_iterator sbi0;
|
||||
vec<operand_entry_t> *subops;
|
||||
htab_t ctable;
|
||||
hash_table <oecount_hasher> ctable;
|
||||
bool changed = false;
|
||||
int next_oecount_id = 0;
|
||||
|
||||
|
@ -1305,7 +1319,7 @@ undistribute_ops_list (enum tree_code opcode,
|
|||
|
||||
/* Build linearized sub-operand lists and the counting table. */
|
||||
cvec.create (0);
|
||||
ctable = htab_create (15, oecount_hash, oecount_eq, NULL);
|
||||
ctable.create (15);
|
||||
/* ??? Macro arguments cannot have multi-argument template types in
|
||||
them. This typedef is needed to workaround that limitation. */
|
||||
typedef vec<operand_entry_t> vec_operand_entry_t_heap;
|
||||
|
@ -1332,7 +1346,7 @@ undistribute_ops_list (enum tree_code opcode,
|
|||
c.op = oe1->op;
|
||||
cvec.safe_push (c);
|
||||
idx = cvec.length () + 41;
|
||||
slot = htab_find_slot (ctable, (void *)idx, INSERT);
|
||||
slot = ctable.find_slot ((void *)idx, INSERT);
|
||||
if (!*slot)
|
||||
{
|
||||
*slot = (void *)idx;
|
||||
|
@ -1344,7 +1358,7 @@ undistribute_ops_list (enum tree_code opcode,
|
|||
}
|
||||
}
|
||||
}
|
||||
htab_delete (ctable);
|
||||
ctable.dispose ();
|
||||
|
||||
/* Sort the counting table. */
|
||||
cvec.qsort (oecount_cmp);
|
||||
|
|
|
@ -29,7 +29,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tree-flow.h"
|
||||
#include "gimple.h"
|
||||
#include "dumpfile.h"
|
||||
#include "hashtab.h"
|
||||
#include "hash-table.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "flags.h"
|
||||
#include "bitmap.h"
|
||||
|
@ -96,19 +96,187 @@ along with GCC; see the file COPYING3. If not see
|
|||
structure copies.
|
||||
*/
|
||||
|
||||
|
||||
/* vn_nary_op hashtable helpers. */
|
||||
|
||||
struct vn_nary_op_hasher : typed_noop_remove <vn_nary_op_s>
|
||||
{
|
||||
typedef vn_nary_op_s value_type;
|
||||
typedef vn_nary_op_s compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* Return the computed hashcode for nary operation P1. */
|
||||
|
||||
inline hashval_t
|
||||
vn_nary_op_hasher::hash (const value_type *vno1)
|
||||
{
|
||||
return vno1->hashcode;
|
||||
}
|
||||
|
||||
/* Compare nary operations P1 and P2 and return true if they are
|
||||
equivalent. */
|
||||
|
||||
inline bool
|
||||
vn_nary_op_hasher::equal (const value_type *vno1, const compare_type *vno2)
|
||||
{
|
||||
return vn_nary_op_eq (vno1, vno2);
|
||||
}
|
||||
|
||||
typedef hash_table <vn_nary_op_hasher> vn_nary_op_table_type;
|
||||
typedef vn_nary_op_table_type::iterator vn_nary_op_iterator_type;
|
||||
|
||||
|
||||
/* vn_phi hashtable helpers. */
|
||||
|
||||
static int
|
||||
vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2);
|
||||
|
||||
struct vn_phi_hasher
|
||||
{
|
||||
typedef vn_phi_s value_type;
|
||||
typedef vn_phi_s compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
static inline void remove (value_type *);
|
||||
};
|
||||
|
||||
/* Return the computed hashcode for phi operation P1. */
|
||||
|
||||
inline hashval_t
|
||||
vn_phi_hasher::hash (const value_type *vp1)
|
||||
{
|
||||
return vp1->hashcode;
|
||||
}
|
||||
|
||||
/* Compare two phi entries for equality, ignoring VN_TOP arguments. */
|
||||
|
||||
inline bool
|
||||
vn_phi_hasher::equal (const value_type *vp1, const compare_type *vp2)
|
||||
{
|
||||
return vn_phi_eq (vp1, vp2);
|
||||
}
|
||||
|
||||
/* Free a phi operation structure VP. */
|
||||
|
||||
inline void
|
||||
vn_phi_hasher::remove (value_type *phi)
|
||||
{
|
||||
phi->phiargs.release ();
|
||||
}
|
||||
|
||||
typedef hash_table <vn_phi_hasher> vn_phi_table_type;
|
||||
typedef vn_phi_table_type::iterator vn_phi_iterator_type;
|
||||
|
||||
|
||||
/* Compare two reference operands P1 and P2 for equality. Return true if
|
||||
they are equal, and false otherwise. */
|
||||
|
||||
static int
|
||||
vn_reference_op_eq (const void *p1, const void *p2)
|
||||
{
|
||||
const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
|
||||
const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
|
||||
|
||||
return (vro1->opcode == vro2->opcode
|
||||
/* We do not care for differences in type qualification. */
|
||||
&& (vro1->type == vro2->type
|
||||
|| (vro1->type && vro2->type
|
||||
&& types_compatible_p (TYPE_MAIN_VARIANT (vro1->type),
|
||||
TYPE_MAIN_VARIANT (vro2->type))))
|
||||
&& expressions_equal_p (vro1->op0, vro2->op0)
|
||||
&& expressions_equal_p (vro1->op1, vro2->op1)
|
||||
&& expressions_equal_p (vro1->op2, vro2->op2));
|
||||
}
|
||||
|
||||
/* Free a reference operation structure VP. */
|
||||
|
||||
static inline void
|
||||
free_reference (vn_reference_s *vr)
|
||||
{
|
||||
vr->operands.release ();
|
||||
}
|
||||
|
||||
|
||||
/* vn_reference hashtable helpers. */
|
||||
|
||||
struct vn_reference_hasher
|
||||
{
|
||||
typedef vn_reference_s value_type;
|
||||
typedef vn_reference_s compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
static inline void remove (value_type *);
|
||||
};
|
||||
|
||||
/* Return the hashcode for a given reference operation P1. */
|
||||
|
||||
inline hashval_t
|
||||
vn_reference_hasher::hash (const value_type *vr1)
|
||||
{
|
||||
return vr1->hashcode;
|
||||
}
|
||||
|
||||
inline bool
|
||||
vn_reference_hasher::equal (const value_type *v, const compare_type *c)
|
||||
{
|
||||
return vn_reference_eq (v, c);
|
||||
}
|
||||
|
||||
inline void
|
||||
vn_reference_hasher::remove (value_type *v)
|
||||
{
|
||||
free_reference (v);
|
||||
}
|
||||
|
||||
typedef hash_table <vn_reference_hasher> vn_reference_table_type;
|
||||
typedef vn_reference_table_type::iterator vn_reference_iterator_type;
|
||||
|
||||
|
||||
/* The set of hashtables and alloc_pool's for their items. */
|
||||
|
||||
typedef struct vn_tables_s
|
||||
{
|
||||
htab_t nary;
|
||||
htab_t phis;
|
||||
htab_t references;
|
||||
vn_nary_op_table_type nary;
|
||||
vn_phi_table_type phis;
|
||||
vn_reference_table_type references;
|
||||
struct obstack nary_obstack;
|
||||
alloc_pool phis_pool;
|
||||
alloc_pool references_pool;
|
||||
} *vn_tables_t;
|
||||
|
||||
static htab_t constant_to_value_id;
|
||||
|
||||
/* vn_constant hashtable helpers. */
|
||||
|
||||
struct vn_constant_hasher : typed_free_remove <vn_constant_s>
|
||||
{
|
||||
typedef vn_constant_s value_type;
|
||||
typedef vn_constant_s compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* Hash table hash function for vn_constant_t. */
|
||||
|
||||
inline hashval_t
|
||||
vn_constant_hasher::hash (const value_type *vc1)
|
||||
{
|
||||
return vc1->hashcode;
|
||||
}
|
||||
|
||||
/* Hash table equality function for vn_constant_t. */
|
||||
|
||||
inline bool
|
||||
vn_constant_hasher::equal (const value_type *vc1, const compare_type *vc2)
|
||||
{
|
||||
if (vc1->hashcode != vc2->hashcode)
|
||||
return false;
|
||||
|
||||
return vn_constant_eq_with_type (vc1->constant, vc2->constant);
|
||||
}
|
||||
|
||||
static hash_table <vn_constant_hasher> constant_to_value_id;
|
||||
static bitmap constant_value_ids;
|
||||
|
||||
|
||||
|
@ -338,62 +506,20 @@ vn_get_stmt_kind (gimple stmt)
|
|||
}
|
||||
}
|
||||
|
||||
/* Free a phi operation structure VP. */
|
||||
|
||||
static void
|
||||
free_phi (void *vp)
|
||||
{
|
||||
vn_phi_t phi = (vn_phi_t) vp;
|
||||
phi->phiargs.release ();
|
||||
}
|
||||
|
||||
/* Free a reference operation structure VP. */
|
||||
|
||||
static void
|
||||
free_reference (void *vp)
|
||||
{
|
||||
vn_reference_t vr = (vn_reference_t) vp;
|
||||
vr->operands.release ();
|
||||
}
|
||||
|
||||
/* Hash table equality function for vn_constant_t. */
|
||||
|
||||
static int
|
||||
vn_constant_eq (const void *p1, const void *p2)
|
||||
{
|
||||
const struct vn_constant_s *vc1 = (const struct vn_constant_s *) p1;
|
||||
const struct vn_constant_s *vc2 = (const struct vn_constant_s *) p2;
|
||||
|
||||
if (vc1->hashcode != vc2->hashcode)
|
||||
return false;
|
||||
|
||||
return vn_constant_eq_with_type (vc1->constant, vc2->constant);
|
||||
}
|
||||
|
||||
/* Hash table hash function for vn_constant_t. */
|
||||
|
||||
static hashval_t
|
||||
vn_constant_hash (const void *p1)
|
||||
{
|
||||
const struct vn_constant_s *vc1 = (const struct vn_constant_s *) p1;
|
||||
return vc1->hashcode;
|
||||
}
|
||||
|
||||
/* Lookup a value id for CONSTANT and return it. If it does not
|
||||
exist returns 0. */
|
||||
|
||||
unsigned int
|
||||
get_constant_value_id (tree constant)
|
||||
{
|
||||
void **slot;
|
||||
vn_constant_s **slot;
|
||||
struct vn_constant_s vc;
|
||||
|
||||
vc.hashcode = vn_hash_constant_with_type (constant);
|
||||
vc.constant = constant;
|
||||
slot = htab_find_slot_with_hash (constant_to_value_id, &vc,
|
||||
vc.hashcode, NO_INSERT);
|
||||
slot = constant_to_value_id.find_slot_with_hash (&vc, vc.hashcode, NO_INSERT);
|
||||
if (slot)
|
||||
return ((vn_constant_t)*slot)->value_id;
|
||||
return (*slot)->value_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -403,22 +529,21 @@ get_constant_value_id (tree constant)
|
|||
unsigned int
|
||||
get_or_alloc_constant_value_id (tree constant)
|
||||
{
|
||||
void **slot;
|
||||
vn_constant_s **slot;
|
||||
struct vn_constant_s vc;
|
||||
vn_constant_t vcp;
|
||||
|
||||
vc.hashcode = vn_hash_constant_with_type (constant);
|
||||
vc.constant = constant;
|
||||
slot = htab_find_slot_with_hash (constant_to_value_id, &vc,
|
||||
vc.hashcode, INSERT);
|
||||
slot = constant_to_value_id.find_slot_with_hash (&vc, vc.hashcode, INSERT);
|
||||
if (*slot)
|
||||
return ((vn_constant_t)*slot)->value_id;
|
||||
return (*slot)->value_id;
|
||||
|
||||
vcp = XNEW (struct vn_constant_s);
|
||||
vcp->hashcode = vc.hashcode;
|
||||
vcp->constant = constant;
|
||||
vcp->value_id = get_next_value_id ();
|
||||
*slot = (void *) vcp;
|
||||
*slot = vcp;
|
||||
bitmap_set_bit (constant_value_ids, vcp->value_id);
|
||||
return vcp->value_id;
|
||||
}
|
||||
|
@ -431,26 +556,6 @@ value_id_constant_p (unsigned int v)
|
|||
return bitmap_bit_p (constant_value_ids, v);
|
||||
}
|
||||
|
||||
/* Compare two reference operands P1 and P2 for equality. Return true if
|
||||
they are equal, and false otherwise. */
|
||||
|
||||
static int
|
||||
vn_reference_op_eq (const void *p1, const void *p2)
|
||||
{
|
||||
const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
|
||||
const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
|
||||
|
||||
return (vro1->opcode == vro2->opcode
|
||||
/* We do not care for differences in type qualification. */
|
||||
&& (vro1->type == vro2->type
|
||||
|| (vro1->type && vro2->type
|
||||
&& types_compatible_p (TYPE_MAIN_VARIANT (vro1->type),
|
||||
TYPE_MAIN_VARIANT (vro2->type))))
|
||||
&& expressions_equal_p (vro1->op0, vro2->op0)
|
||||
&& expressions_equal_p (vro1->op1, vro2->op1)
|
||||
&& expressions_equal_p (vro1->op2, vro2->op2));
|
||||
}
|
||||
|
||||
/* Compute the hash for a reference operand VRO1. */
|
||||
|
||||
static hashval_t
|
||||
|
@ -466,15 +571,6 @@ vn_reference_op_compute_hash (const vn_reference_op_t vro1, hashval_t result)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Return the hashcode for a given reference operation P1. */
|
||||
|
||||
static hashval_t
|
||||
vn_reference_hash (const void *p1)
|
||||
{
|
||||
const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
|
||||
return vr1->hashcode;
|
||||
}
|
||||
|
||||
/* Compute a hash for the reference operation VR1 and return it. */
|
||||
|
||||
hashval_t
|
||||
|
@ -524,16 +620,14 @@ vn_reference_compute_hash (const vn_reference_t vr1)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Return true if reference operations P1 and P2 are equivalent. This
|
||||
/* Return true if reference operations VR1 and VR2 are equivalent. This
|
||||
means they have the same set of operands and vuses. */
|
||||
|
||||
int
|
||||
vn_reference_eq (const void *p1, const void *p2)
|
||||
bool
|
||||
vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
|
||||
const_vn_reference_t const vr2 = (const_vn_reference_t) p2;
|
||||
if (vr1->hashcode != vr2->hashcode)
|
||||
return false;
|
||||
|
||||
|
@ -1346,15 +1440,13 @@ valueize_shared_reference_ops_from_call (gimple call)
|
|||
static tree
|
||||
vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
|
||||
{
|
||||
void **slot;
|
||||
vn_reference_s **slot;
|
||||
hashval_t hash;
|
||||
|
||||
hash = vr->hashcode;
|
||||
slot = htab_find_slot_with_hash (current_info->references, vr,
|
||||
hash, NO_INSERT);
|
||||
slot = current_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
|
||||
if (!slot && current_info == optimistic_info)
|
||||
slot = htab_find_slot_with_hash (valid_info->references, vr,
|
||||
hash, NO_INSERT);
|
||||
slot = valid_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
|
||||
if (slot)
|
||||
{
|
||||
if (vnresult)
|
||||
|
@ -1377,7 +1469,7 @@ vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse,
|
|||
unsigned int cnt, void *vr_)
|
||||
{
|
||||
vn_reference_t vr = (vn_reference_t)vr_;
|
||||
void **slot;
|
||||
vn_reference_s **slot;
|
||||
hashval_t hash;
|
||||
|
||||
/* This bounds the stmt walks we perform on reference lookups
|
||||
|
@ -1397,11 +1489,9 @@ vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse,
|
|||
vr->hashcode = vr->hashcode + SSA_NAME_VERSION (vr->vuse);
|
||||
|
||||
hash = vr->hashcode;
|
||||
slot = htab_find_slot_with_hash (current_info->references, vr,
|
||||
hash, NO_INSERT);
|
||||
slot = current_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
|
||||
if (!slot && current_info == optimistic_info)
|
||||
slot = htab_find_slot_with_hash (valid_info->references, vr,
|
||||
hash, NO_INSERT);
|
||||
slot = valid_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
|
||||
if (slot)
|
||||
return *slot;
|
||||
|
||||
|
@ -2004,7 +2094,7 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
|
|||
vn_reference_t
|
||||
vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
|
||||
{
|
||||
void **slot;
|
||||
vn_reference_s **slot;
|
||||
vn_reference_t vr1;
|
||||
|
||||
vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
|
||||
|
@ -2020,8 +2110,8 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
|
|||
vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
|
||||
vr1->result_vdef = vdef;
|
||||
|
||||
slot = htab_find_slot_with_hash (current_info->references, vr1, vr1->hashcode,
|
||||
INSERT);
|
||||
slot = current_info->references.find_slot_with_hash (vr1, vr1->hashcode,
|
||||
INSERT);
|
||||
|
||||
/* Because we lookup stores using vuses, and value number failures
|
||||
using the vdefs (see visit_reference_op_store for how and why),
|
||||
|
@ -2049,7 +2139,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
|
|||
tree result, unsigned int value_id)
|
||||
|
||||
{
|
||||
void **slot;
|
||||
vn_reference_s **slot;
|
||||
vn_reference_t vr1;
|
||||
|
||||
vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
|
||||
|
@ -2063,8 +2153,8 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
|
|||
result = SSA_VAL (result);
|
||||
vr1->result = result;
|
||||
|
||||
slot = htab_find_slot_with_hash (current_info->references, vr1, vr1->hashcode,
|
||||
INSERT);
|
||||
slot = current_info->references.find_slot_with_hash (vr1, vr1->hashcode,
|
||||
INSERT);
|
||||
|
||||
/* At this point we should have all the things inserted that we have
|
||||
seen before, and we should never try inserting something that
|
||||
|
@ -2105,23 +2195,12 @@ vn_nary_op_compute_hash (const vn_nary_op_t vno1)
|
|||
return hash;
|
||||
}
|
||||
|
||||
/* Return the computed hashcode for nary operation P1. */
|
||||
|
||||
static hashval_t
|
||||
vn_nary_op_hash (const void *p1)
|
||||
{
|
||||
const_vn_nary_op_t const vno1 = (const_vn_nary_op_t) p1;
|
||||
return vno1->hashcode;
|
||||
}
|
||||
|
||||
/* Compare nary operations P1 and P2 and return true if they are
|
||||
/* Compare nary operations VNO1 and VNO2 and return true if they are
|
||||
equivalent. */
|
||||
|
||||
int
|
||||
vn_nary_op_eq (const void *p1, const void *p2)
|
||||
bool
|
||||
vn_nary_op_eq (const_vn_nary_op_t const vno1, const_vn_nary_op_t const vno2)
|
||||
{
|
||||
const_vn_nary_op_t const vno1 = (const_vn_nary_op_t) p1;
|
||||
const_vn_nary_op_t const vno2 = (const_vn_nary_op_t) p2;
|
||||
unsigned i;
|
||||
|
||||
if (vno1->hashcode != vno2->hashcode)
|
||||
|
@ -2238,22 +2317,20 @@ init_vn_nary_op_from_stmt (vn_nary_op_t vno, gimple stmt)
|
|||
static tree
|
||||
vn_nary_op_lookup_1 (vn_nary_op_t vno, vn_nary_op_t *vnresult)
|
||||
{
|
||||
void **slot;
|
||||
vn_nary_op_s **slot;
|
||||
|
||||
if (vnresult)
|
||||
*vnresult = NULL;
|
||||
|
||||
vno->hashcode = vn_nary_op_compute_hash (vno);
|
||||
slot = htab_find_slot_with_hash (current_info->nary, vno, vno->hashcode,
|
||||
NO_INSERT);
|
||||
slot = current_info->nary.find_slot_with_hash (vno, vno->hashcode, NO_INSERT);
|
||||
if (!slot && current_info == optimistic_info)
|
||||
slot = htab_find_slot_with_hash (valid_info->nary, vno, vno->hashcode,
|
||||
NO_INSERT);
|
||||
slot = valid_info->nary.find_slot_with_hash (vno, vno->hashcode, NO_INSERT);
|
||||
if (!slot)
|
||||
return NULL_TREE;
|
||||
if (vnresult)
|
||||
*vnresult = (vn_nary_op_t)*slot;
|
||||
return ((vn_nary_op_t)*slot)->result;
|
||||
*vnresult = *slot;
|
||||
return (*slot)->result;
|
||||
}
|
||||
|
||||
/* Lookup a n-ary operation by its pieces and return the resulting value
|
||||
|
@ -2331,14 +2408,15 @@ alloc_vn_nary_op (unsigned int length, tree result, unsigned int value_id)
|
|||
VNO->HASHCODE first. */
|
||||
|
||||
static vn_nary_op_t
|
||||
vn_nary_op_insert_into (vn_nary_op_t vno, htab_t table, bool compute_hash)
|
||||
vn_nary_op_insert_into (vn_nary_op_t vno, vn_nary_op_table_type table,
|
||||
bool compute_hash)
|
||||
{
|
||||
void **slot;
|
||||
vn_nary_op_s **slot;
|
||||
|
||||
if (compute_hash)
|
||||
vno->hashcode = vn_nary_op_compute_hash (vno);
|
||||
|
||||
slot = htab_find_slot_with_hash (table, vno, vno->hashcode, INSERT);
|
||||
slot = table.find_slot_with_hash (vno, vno->hashcode, INSERT);
|
||||
gcc_assert (!*slot);
|
||||
|
||||
*slot = vno;
|
||||
|
@ -2414,23 +2492,11 @@ vn_phi_compute_hash (vn_phi_t vp1)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Return the computed hashcode for phi operation P1. */
|
||||
|
||||
static hashval_t
|
||||
vn_phi_hash (const void *p1)
|
||||
{
|
||||
const_vn_phi_t const vp1 = (const_vn_phi_t) p1;
|
||||
return vp1->hashcode;
|
||||
}
|
||||
|
||||
/* Compare two phi entries for equality, ignoring VN_TOP arguments. */
|
||||
|
||||
static int
|
||||
vn_phi_eq (const void *p1, const void *p2)
|
||||
vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2)
|
||||
{
|
||||
const_vn_phi_t const vp1 = (const_vn_phi_t) p1;
|
||||
const_vn_phi_t const vp2 = (const_vn_phi_t) p2;
|
||||
|
||||
if (vp1->hashcode != vp2->hashcode)
|
||||
return false;
|
||||
|
||||
|
@ -2468,7 +2534,7 @@ static vec<tree> shared_lookup_phiargs;
|
|||
static tree
|
||||
vn_phi_lookup (gimple phi)
|
||||
{
|
||||
void **slot;
|
||||
vn_phi_s **slot;
|
||||
struct vn_phi_s vp1;
|
||||
unsigned i;
|
||||
|
||||
|
@ -2485,14 +2551,12 @@ vn_phi_lookup (gimple phi)
|
|||
vp1.phiargs = shared_lookup_phiargs;
|
||||
vp1.block = gimple_bb (phi);
|
||||
vp1.hashcode = vn_phi_compute_hash (&vp1);
|
||||
slot = htab_find_slot_with_hash (current_info->phis, &vp1, vp1.hashcode,
|
||||
NO_INSERT);
|
||||
slot = current_info->phis.find_slot_with_hash (&vp1, vp1.hashcode, NO_INSERT);
|
||||
if (!slot && current_info == optimistic_info)
|
||||
slot = htab_find_slot_with_hash (valid_info->phis, &vp1, vp1.hashcode,
|
||||
NO_INSERT);
|
||||
slot = valid_info->phis.find_slot_with_hash (&vp1, vp1.hashcode, NO_INSERT);
|
||||
if (!slot)
|
||||
return NULL_TREE;
|
||||
return ((vn_phi_t)*slot)->result;
|
||||
return (*slot)->result;
|
||||
}
|
||||
|
||||
/* Insert PHI into the current hash table with a value number of
|
||||
|
@ -2501,7 +2565,7 @@ vn_phi_lookup (gimple phi)
|
|||
static vn_phi_t
|
||||
vn_phi_insert (gimple phi, tree result)
|
||||
{
|
||||
void **slot;
|
||||
vn_phi_s **slot;
|
||||
vn_phi_t vp1 = (vn_phi_t) pool_alloc (current_info->phis_pool);
|
||||
unsigned i;
|
||||
vec<tree> args = vNULL;
|
||||
|
@ -2520,8 +2584,7 @@ vn_phi_insert (gimple phi, tree result)
|
|||
vp1->result = result;
|
||||
vp1->hashcode = vn_phi_compute_hash (vp1);
|
||||
|
||||
slot = htab_find_slot_with_hash (current_info->phis, vp1, vp1->hashcode,
|
||||
INSERT);
|
||||
slot = current_info->phis.find_slot_with_hash (vp1, vp1->hashcode, INSERT);
|
||||
|
||||
/* Because we iterate over phi operations more than once, it's
|
||||
possible the slot might already exist here, hence no assert.*/
|
||||
|
@ -2724,7 +2787,7 @@ visit_reference_op_call (tree lhs, gimple stmt)
|
|||
}
|
||||
else
|
||||
{
|
||||
void **slot;
|
||||
vn_reference_s **slot;
|
||||
vn_reference_t vr2;
|
||||
if (vdef)
|
||||
changed |= set_ssa_val_to (vdef, vdef);
|
||||
|
@ -2738,8 +2801,8 @@ visit_reference_op_call (tree lhs, gimple stmt)
|
|||
vr2->hashcode = vr1.hashcode;
|
||||
vr2->result = lhs;
|
||||
vr2->result_vdef = vdef;
|
||||
slot = htab_find_slot_with_hash (current_info->references,
|
||||
vr2, vr2->hashcode, INSERT);
|
||||
slot = current_info->references.find_slot_with_hash (vr2, vr2->hashcode,
|
||||
INSERT);
|
||||
if (*slot)
|
||||
free_reference (*slot);
|
||||
*slot = vr2;
|
||||
|
@ -3599,10 +3662,10 @@ static void
|
|||
copy_phi (vn_phi_t ophi, vn_tables_t info)
|
||||
{
|
||||
vn_phi_t phi = (vn_phi_t) pool_alloc (info->phis_pool);
|
||||
void **slot;
|
||||
vn_phi_s **slot;
|
||||
memcpy (phi, ophi, sizeof (*phi));
|
||||
ophi->phiargs.create (0);
|
||||
slot = htab_find_slot_with_hash (info->phis, phi, phi->hashcode, INSERT);
|
||||
slot = info->phis.find_slot_with_hash (phi, phi->hashcode, INSERT);
|
||||
gcc_assert (!*slot);
|
||||
*slot = phi;
|
||||
}
|
||||
|
@ -3613,12 +3676,11 @@ static void
|
|||
copy_reference (vn_reference_t oref, vn_tables_t info)
|
||||
{
|
||||
vn_reference_t ref;
|
||||
void **slot;
|
||||
vn_reference_s **slot;
|
||||
ref = (vn_reference_t) pool_alloc (info->references_pool);
|
||||
memcpy (ref, oref, sizeof (*ref));
|
||||
oref->operands.create (0);
|
||||
slot = htab_find_slot_with_hash (info->references, ref, ref->hashcode,
|
||||
INSERT);
|
||||
slot = info->references.find_slot_with_hash (ref, ref->hashcode, INSERT);
|
||||
if (*slot)
|
||||
free_reference (*slot);
|
||||
*slot = ref;
|
||||
|
@ -3633,7 +3695,9 @@ process_scc (vec<tree> scc)
|
|||
unsigned int i;
|
||||
unsigned int iterations = 0;
|
||||
bool changed = true;
|
||||
htab_iterator hi;
|
||||
vn_nary_op_iterator_type hin;
|
||||
vn_phi_iterator_type hip;
|
||||
vn_reference_iterator_type hir;
|
||||
vn_nary_op_t nary;
|
||||
vn_phi_t phi;
|
||||
vn_reference_t ref;
|
||||
|
@ -3670,9 +3734,9 @@ process_scc (vec<tree> scc)
|
|||
/* As we are value-numbering optimistically we have to
|
||||
clear the expression tables and the simplified expressions
|
||||
in each iteration until we converge. */
|
||||
htab_empty (optimistic_info->nary);
|
||||
htab_empty (optimistic_info->phis);
|
||||
htab_empty (optimistic_info->references);
|
||||
optimistic_info->nary.empty ();
|
||||
optimistic_info->phis.empty ();
|
||||
optimistic_info->references.empty ();
|
||||
obstack_free (&optimistic_info->nary_obstack, NULL);
|
||||
gcc_obstack_init (&optimistic_info->nary_obstack);
|
||||
empty_alloc_pool (optimistic_info->phis_pool);
|
||||
|
@ -3687,11 +3751,12 @@ process_scc (vec<tree> scc)
|
|||
|
||||
/* Finally, copy the contents of the no longer used optimistic
|
||||
table to the valid table. */
|
||||
FOR_EACH_HTAB_ELEMENT (optimistic_info->nary, nary, vn_nary_op_t, hi)
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (optimistic_info->nary, nary, vn_nary_op_t, hin)
|
||||
copy_nary (nary, valid_info);
|
||||
FOR_EACH_HTAB_ELEMENT (optimistic_info->phis, phi, vn_phi_t, hi)
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (optimistic_info->phis, phi, vn_phi_t, hip)
|
||||
copy_phi (phi, valid_info);
|
||||
FOR_EACH_HTAB_ELEMENT (optimistic_info->references, ref, vn_reference_t, hi)
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (optimistic_info->references,
|
||||
ref, vn_reference_t, hir)
|
||||
copy_reference (ref, valid_info);
|
||||
|
||||
current_info = valid_info;
|
||||
|
@ -3851,10 +3916,9 @@ continue_walking:
|
|||
static void
|
||||
allocate_vn_table (vn_tables_t table)
|
||||
{
|
||||
table->phis = htab_create (23, vn_phi_hash, vn_phi_eq, free_phi);
|
||||
table->nary = htab_create (23, vn_nary_op_hash, vn_nary_op_eq, NULL);
|
||||
table->references = htab_create (23, vn_reference_hash, vn_reference_eq,
|
||||
free_reference);
|
||||
table->phis.create (23);
|
||||
table->nary.create (23);
|
||||
table->references.create (23);
|
||||
|
||||
gcc_obstack_init (&table->nary_obstack);
|
||||
table->phis_pool = create_alloc_pool ("VN phis",
|
||||
|
@ -3870,9 +3934,9 @@ allocate_vn_table (vn_tables_t table)
|
|||
static void
|
||||
free_vn_table (vn_tables_t table)
|
||||
{
|
||||
htab_delete (table->phis);
|
||||
htab_delete (table->nary);
|
||||
htab_delete (table->references);
|
||||
table->phis.dispose ();
|
||||
table->nary.dispose ();
|
||||
table->references.dispose ();
|
||||
obstack_free (&table->nary_obstack, NULL);
|
||||
free_alloc_pool (table->phis_pool);
|
||||
free_alloc_pool (table->references_pool);
|
||||
|
@ -3887,8 +3951,7 @@ init_scc_vn (void)
|
|||
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
sccstack.create (0);
|
||||
constant_to_value_id = htab_create (23, vn_constant_hash, vn_constant_eq,
|
||||
free);
|
||||
constant_to_value_id.create (23);
|
||||
|
||||
constant_value_ids = BITMAP_ALLOC (NULL);
|
||||
|
||||
|
@ -3944,7 +4007,7 @@ free_scc_vn (void)
|
|||
{
|
||||
size_t i;
|
||||
|
||||
htab_delete (constant_to_value_id);
|
||||
constant_to_value_id.dispose ();
|
||||
BITMAP_FREE (constant_value_ids);
|
||||
shared_lookup_phiargs.release ();
|
||||
shared_lookup_references.release ();
|
||||
|
@ -3985,7 +4048,9 @@ set_value_id_for_result (tree result, unsigned int *id)
|
|||
static void
|
||||
set_hashtable_value_ids (void)
|
||||
{
|
||||
htab_iterator hi;
|
||||
vn_nary_op_iterator_type hin;
|
||||
vn_phi_iterator_type hip;
|
||||
vn_reference_iterator_type hir;
|
||||
vn_nary_op_t vno;
|
||||
vn_reference_t vr;
|
||||
vn_phi_t vp;
|
||||
|
@ -3993,16 +4058,13 @@ set_hashtable_value_ids (void)
|
|||
/* Now set the value ids of the things we had put in the hash
|
||||
table. */
|
||||
|
||||
FOR_EACH_HTAB_ELEMENT (valid_info->nary,
|
||||
vno, vn_nary_op_t, hi)
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (valid_info->nary, vno, vn_nary_op_t, hin)
|
||||
set_value_id_for_result (vno->result, &vno->value_id);
|
||||
|
||||
FOR_EACH_HTAB_ELEMENT (valid_info->phis,
|
||||
vp, vn_phi_t, hi)
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (valid_info->phis, vp, vn_phi_t, hip)
|
||||
set_value_id_for_result (vp->result, &vp->value_id);
|
||||
|
||||
FOR_EACH_HTAB_ELEMENT (valid_info->references,
|
||||
vr, vn_reference_t, hi)
|
||||
FOR_EACH_HASH_TABLE_ELEMENT (valid_info->references, vr, vn_reference_t, hir)
|
||||
set_value_id_for_result (vr->result, &vr->value_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -216,10 +216,11 @@ vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree,
|
|||
tree, unsigned int);
|
||||
|
||||
hashval_t vn_nary_op_compute_hash (const vn_nary_op_t);
|
||||
int vn_nary_op_eq (const void *, const void *);
|
||||
bool vn_nary_op_eq (const_vn_nary_op_t const vno1,
|
||||
const_vn_nary_op_t const vno2);
|
||||
bool vn_nary_may_trap (vn_nary_op_t);
|
||||
hashval_t vn_reference_compute_hash (const vn_reference_t);
|
||||
int vn_reference_eq (const void *, const void *);
|
||||
bool vn_reference_eq (const_vn_reference_t const, const_vn_reference_t const);
|
||||
unsigned int get_max_value_id (void);
|
||||
unsigned int get_next_value_id (void);
|
||||
unsigned int get_constant_value_id (tree);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "tree-inline.h"
|
||||
#include "diagnostic-core.h"
|
||||
#include "gimple.h"
|
||||
#include "hashtab.h"
|
||||
#include "hash-table.h"
|
||||
#include "function.h"
|
||||
#include "cgraph.h"
|
||||
#include "tree-pass.h"
|
||||
|
@ -1862,48 +1862,54 @@ typedef struct equiv_class_label
|
|||
} *equiv_class_label_t;
|
||||
typedef const struct equiv_class_label *const_equiv_class_label_t;
|
||||
|
||||
/* A hashtable for mapping a bitmap of labels->pointer equivalence
|
||||
classes. */
|
||||
static htab_t pointer_equiv_class_table;
|
||||
/* Equiv_class_label hashtable helpers. */
|
||||
|
||||
/* A hashtable for mapping a bitmap of labels->location equivalence
|
||||
classes. */
|
||||
static htab_t location_equiv_class_table;
|
||||
struct equiv_class_hasher : typed_free_remove <equiv_class_label>
|
||||
{
|
||||
typedef equiv_class_label value_type;
|
||||
typedef equiv_class_label compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* Hash function for a equiv_class_label_t */
|
||||
|
||||
static hashval_t
|
||||
equiv_class_label_hash (const void *p)
|
||||
inline hashval_t
|
||||
equiv_class_hasher::hash (const value_type *ecl)
|
||||
{
|
||||
const_equiv_class_label_t const ecl = (const_equiv_class_label_t) p;
|
||||
return ecl->hashcode;
|
||||
}
|
||||
|
||||
/* Equality function for two equiv_class_label_t's. */
|
||||
|
||||
static int
|
||||
equiv_class_label_eq (const void *p1, const void *p2)
|
||||
inline bool
|
||||
equiv_class_hasher::equal (const value_type *eql1, const compare_type *eql2)
|
||||
{
|
||||
const_equiv_class_label_t const eql1 = (const_equiv_class_label_t) p1;
|
||||
const_equiv_class_label_t const eql2 = (const_equiv_class_label_t) p2;
|
||||
return (eql1->hashcode == eql2->hashcode
|
||||
&& bitmap_equal_p (eql1->labels, eql2->labels));
|
||||
}
|
||||
|
||||
/* A hashtable for mapping a bitmap of labels->pointer equivalence
|
||||
classes. */
|
||||
static hash_table <equiv_class_hasher> pointer_equiv_class_table;
|
||||
|
||||
/* A hashtable for mapping a bitmap of labels->location equivalence
|
||||
classes. */
|
||||
static hash_table <equiv_class_hasher> location_equiv_class_table;
|
||||
|
||||
/* Lookup a equivalence class in TABLE by the bitmap of LABELS with
|
||||
hash HAS it contains. Sets *REF_LABELS to the bitmap LABELS
|
||||
is equivalent to. */
|
||||
|
||||
static equiv_class_label *
|
||||
equiv_class_lookup_or_add (htab_t table, bitmap labels)
|
||||
equiv_class_lookup_or_add (hash_table <equiv_class_hasher> table, bitmap labels)
|
||||
{
|
||||
equiv_class_label **slot;
|
||||
equiv_class_label ecl;
|
||||
|
||||
ecl.labels = labels;
|
||||
ecl.hashcode = bitmap_hash (labels);
|
||||
slot = (equiv_class_label **) htab_find_slot_with_hash (table, &ecl,
|
||||
ecl.hashcode, INSERT);
|
||||
slot = table.find_slot_with_hash (&ecl, ecl.hashcode, INSERT);
|
||||
if (!*slot)
|
||||
{
|
||||
*slot = XNEW (struct equiv_class_label);
|
||||
|
@ -2222,10 +2228,8 @@ perform_var_substitution (constraint_graph_t graph)
|
|||
struct scc_info *si = init_scc_info (size);
|
||||
|
||||
bitmap_obstack_initialize (&iteration_obstack);
|
||||
pointer_equiv_class_table = htab_create (511, equiv_class_label_hash,
|
||||
equiv_class_label_eq, free);
|
||||
location_equiv_class_table = htab_create (511, equiv_class_label_hash,
|
||||
equiv_class_label_eq, free);
|
||||
pointer_equiv_class_table.create (511);
|
||||
location_equiv_class_table.create (511);
|
||||
pointer_equiv_class = 1;
|
||||
location_equiv_class = 1;
|
||||
|
||||
|
@ -2358,8 +2362,8 @@ free_var_substitution_info (struct scc_info *si)
|
|||
free (graph->points_to);
|
||||
free (graph->eq_rep);
|
||||
sbitmap_free (graph->direct_nodes);
|
||||
htab_delete (pointer_equiv_class_table);
|
||||
htab_delete (location_equiv_class_table);
|
||||
pointer_equiv_class_table.dispose ();
|
||||
location_equiv_class_table.dispose ();
|
||||
bitmap_obstack_release (&iteration_obstack);
|
||||
}
|
||||
|
||||
|
@ -5900,45 +5904,54 @@ typedef struct shared_bitmap_info
|
|||
} *shared_bitmap_info_t;
|
||||
typedef const struct shared_bitmap_info *const_shared_bitmap_info_t;
|
||||
|
||||
static htab_t shared_bitmap_table;
|
||||
/* Shared_bitmap hashtable helpers. */
|
||||
|
||||
struct shared_bitmap_hasher : typed_free_remove <shared_bitmap_info>
|
||||
{
|
||||
typedef shared_bitmap_info value_type;
|
||||
typedef shared_bitmap_info compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
/* Hash function for a shared_bitmap_info_t */
|
||||
|
||||
static hashval_t
|
||||
shared_bitmap_hash (const void *p)
|
||||
inline hashval_t
|
||||
shared_bitmap_hasher::hash (const value_type *bi)
|
||||
{
|
||||
const_shared_bitmap_info_t const bi = (const_shared_bitmap_info_t) p;
|
||||
return bi->hashcode;
|
||||
}
|
||||
|
||||
/* Equality function for two shared_bitmap_info_t's. */
|
||||
|
||||
static int
|
||||
shared_bitmap_eq (const void *p1, const void *p2)
|
||||
inline bool
|
||||
shared_bitmap_hasher::equal (const value_type *sbi1, const compare_type *sbi2)
|
||||
{
|
||||
const_shared_bitmap_info_t const sbi1 = (const_shared_bitmap_info_t) p1;
|
||||
const_shared_bitmap_info_t const sbi2 = (const_shared_bitmap_info_t) p2;
|
||||
return bitmap_equal_p (sbi1->pt_vars, sbi2->pt_vars);
|
||||
}
|
||||
|
||||
/* Shared_bitmap hashtable. */
|
||||
|
||||
static hash_table <shared_bitmap_hasher> shared_bitmap_table;
|
||||
|
||||
/* Lookup a bitmap in the shared bitmap hashtable, and return an already
|
||||
existing instance if there is one, NULL otherwise. */
|
||||
|
||||
static bitmap
|
||||
shared_bitmap_lookup (bitmap pt_vars)
|
||||
{
|
||||
void **slot;
|
||||
shared_bitmap_info **slot;
|
||||
struct shared_bitmap_info sbi;
|
||||
|
||||
sbi.pt_vars = pt_vars;
|
||||
sbi.hashcode = bitmap_hash (pt_vars);
|
||||
|
||||
slot = htab_find_slot_with_hash (shared_bitmap_table, &sbi,
|
||||
sbi.hashcode, NO_INSERT);
|
||||
slot = shared_bitmap_table.find_slot_with_hash (&sbi, sbi.hashcode,
|
||||
NO_INSERT);
|
||||
if (!slot)
|
||||
return NULL;
|
||||
else
|
||||
return ((shared_bitmap_info_t) *slot)->pt_vars;
|
||||
return (*slot)->pt_vars;
|
||||
}
|
||||
|
||||
|
||||
|
@ -5947,16 +5960,15 @@ shared_bitmap_lookup (bitmap pt_vars)
|
|||
static void
|
||||
shared_bitmap_add (bitmap pt_vars)
|
||||
{
|
||||
void **slot;
|
||||
shared_bitmap_info **slot;
|
||||
shared_bitmap_info_t sbi = XNEW (struct shared_bitmap_info);
|
||||
|
||||
sbi->pt_vars = pt_vars;
|
||||
sbi->hashcode = bitmap_hash (pt_vars);
|
||||
|
||||
slot = htab_find_slot_with_hash (shared_bitmap_table, sbi,
|
||||
sbi->hashcode, INSERT);
|
||||
slot = shared_bitmap_table.find_slot_with_hash (sbi, sbi->hashcode, INSERT);
|
||||
gcc_assert (!*slot);
|
||||
*slot = (void *) sbi;
|
||||
*slot = sbi;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6612,8 +6624,7 @@ init_alias_vars (void)
|
|||
call_stmt_vars = pointer_map_create ();
|
||||
|
||||
memset (&stats, 0, sizeof (stats));
|
||||
shared_bitmap_table = htab_create (511, shared_bitmap_hash,
|
||||
shared_bitmap_eq, free);
|
||||
shared_bitmap_table.create (511);
|
||||
init_base_vars ();
|
||||
|
||||
gcc_obstack_init (&fake_var_decl_obstack);
|
||||
|
@ -6869,7 +6880,7 @@ delete_points_to_sets (void)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
htab_delete (shared_bitmap_table);
|
||||
shared_bitmap_table.dispose ();
|
||||
if (dump_file && (dump_flags & TDF_STATS))
|
||||
fprintf (dump_file, "Points to sets created:%d\n",
|
||||
stats.points_to_sets_created);
|
||||
|
|
|
@ -1062,27 +1062,6 @@ vect_get_data_access_cost (struct data_reference *dr,
|
|||
}
|
||||
|
||||
|
||||
static hashval_t
|
||||
vect_peeling_hash (const void *elem)
|
||||
{
|
||||
const struct _vect_peel_info *peel_info;
|
||||
|
||||
peel_info = (const struct _vect_peel_info *) elem;
|
||||
return (hashval_t) peel_info->npeel;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vect_peeling_hash_eq (const void *elem1, const void *elem2)
|
||||
{
|
||||
const struct _vect_peel_info *a, *b;
|
||||
|
||||
a = (const struct _vect_peel_info *) elem1;
|
||||
b = (const struct _vect_peel_info *) elem2;
|
||||
return (a->npeel == b->npeel);
|
||||
}
|
||||
|
||||
|
||||
/* Insert DR into peeling hash table with NPEEL as key. */
|
||||
|
||||
static void
|
||||
|
@ -1090,12 +1069,11 @@ vect_peeling_hash_insert (loop_vec_info loop_vinfo, struct data_reference *dr,
|
|||
int npeel)
|
||||
{
|
||||
struct _vect_peel_info elem, *slot;
|
||||
void **new_slot;
|
||||
_vect_peel_info **new_slot;
|
||||
bool supportable_dr_alignment = vect_supportable_dr_alignment (dr, true);
|
||||
|
||||
elem.npeel = npeel;
|
||||
slot = (vect_peel_info) htab_find (LOOP_VINFO_PEELING_HTAB (loop_vinfo),
|
||||
&elem);
|
||||
slot = LOOP_VINFO_PEELING_HTAB (loop_vinfo).find (&elem);
|
||||
if (slot)
|
||||
slot->count++;
|
||||
else
|
||||
|
@ -1104,8 +1082,7 @@ vect_peeling_hash_insert (loop_vec_info loop_vinfo, struct data_reference *dr,
|
|||
slot->npeel = npeel;
|
||||
slot->dr = dr;
|
||||
slot->count = 1;
|
||||
new_slot = htab_find_slot (LOOP_VINFO_PEELING_HTAB (loop_vinfo), slot,
|
||||
INSERT);
|
||||
new_slot = LOOP_VINFO_PEELING_HTAB (loop_vinfo).find_slot (slot, INSERT);
|
||||
*new_slot = slot;
|
||||
}
|
||||
|
||||
|
@ -1117,11 +1094,11 @@ vect_peeling_hash_insert (loop_vec_info loop_vinfo, struct data_reference *dr,
|
|||
/* Traverse peeling hash table to find peeling option that aligns maximum
|
||||
number of data accesses. */
|
||||
|
||||
static int
|
||||
vect_peeling_hash_get_most_frequent (void **slot, void *data)
|
||||
int
|
||||
vect_peeling_hash_get_most_frequent (_vect_peel_info **slot,
|
||||
_vect_peel_extended_info *max)
|
||||
{
|
||||
vect_peel_info elem = (vect_peel_info) *slot;
|
||||
vect_peel_extended_info max = (vect_peel_extended_info) data;
|
||||
vect_peel_info elem = *slot;
|
||||
|
||||
if (elem->count > max->peel_info.count
|
||||
|| (elem->count == max->peel_info.count
|
||||
|
@ -1139,11 +1116,11 @@ vect_peeling_hash_get_most_frequent (void **slot, void *data)
|
|||
/* Traverse peeling hash table and calculate cost for each peeling option.
|
||||
Find the one with the lowest cost. */
|
||||
|
||||
static int
|
||||
vect_peeling_hash_get_lowest_cost (void **slot, void *data)
|
||||
int
|
||||
vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
|
||||
_vect_peel_extended_info *min)
|
||||
{
|
||||
vect_peel_info elem = (vect_peel_info) *slot;
|
||||
vect_peel_extended_info min = (vect_peel_extended_info) data;
|
||||
vect_peel_info elem = *slot;
|
||||
int save_misalignment, dummy;
|
||||
unsigned int inside_cost = 0, outside_cost = 0, i;
|
||||
gimple stmt = DR_STMT (elem->dr);
|
||||
|
@ -1223,14 +1200,16 @@ vect_peeling_hash_choose_best_peeling (loop_vec_info loop_vinfo,
|
|||
{
|
||||
res.inside_cost = INT_MAX;
|
||||
res.outside_cost = INT_MAX;
|
||||
htab_traverse (LOOP_VINFO_PEELING_HTAB (loop_vinfo),
|
||||
vect_peeling_hash_get_lowest_cost, &res);
|
||||
LOOP_VINFO_PEELING_HTAB (loop_vinfo)
|
||||
.traverse <_vect_peel_extended_info *,
|
||||
vect_peeling_hash_get_lowest_cost> (&res);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.peel_info.count = 0;
|
||||
htab_traverse (LOOP_VINFO_PEELING_HTAB (loop_vinfo),
|
||||
vect_peeling_hash_get_most_frequent, &res);
|
||||
LOOP_VINFO_PEELING_HTAB (loop_vinfo)
|
||||
.traverse <_vect_peel_extended_info *,
|
||||
vect_peeling_hash_get_most_frequent> (&res);
|
||||
}
|
||||
|
||||
*npeel = res.peel_info.npeel;
|
||||
|
@ -1423,10 +1402,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
|
|||
size_zero_node) < 0;
|
||||
|
||||
/* Save info about DR in the hash table. */
|
||||
if (!LOOP_VINFO_PEELING_HTAB (loop_vinfo))
|
||||
LOOP_VINFO_PEELING_HTAB (loop_vinfo) =
|
||||
htab_create (1, vect_peeling_hash,
|
||||
vect_peeling_hash_eq, free);
|
||||
if (!LOOP_VINFO_PEELING_HTAB (loop_vinfo).is_created ())
|
||||
LOOP_VINFO_PEELING_HTAB (loop_vinfo).create (1);
|
||||
|
||||
vectype = STMT_VINFO_VECTYPE (stmt_info);
|
||||
nelements = TYPE_VECTOR_SUBPARTS (vectype);
|
||||
|
|
|
@ -879,7 +879,6 @@ new_loop_vec_info (struct loop *loop)
|
|||
LOOP_VINFO_REDUCTION_CHAINS (res).create (10);
|
||||
LOOP_VINFO_SLP_INSTANCES (res).create (10);
|
||||
LOOP_VINFO_SLP_UNROLLING_FACTOR (res) = 1;
|
||||
LOOP_VINFO_PEELING_HTAB (res) = NULL;
|
||||
LOOP_VINFO_TARGET_COST_DATA (res) = init_cost (loop);
|
||||
LOOP_VINFO_PEELING_FOR_GAPS (res) = false;
|
||||
LOOP_VINFO_OPERANDS_SWAPPED (res) = false;
|
||||
|
@ -960,8 +959,8 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo, bool clean_stmts)
|
|||
LOOP_VINFO_REDUCTIONS (loop_vinfo).release ();
|
||||
LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo).release ();
|
||||
|
||||
if (LOOP_VINFO_PEELING_HTAB (loop_vinfo))
|
||||
htab_delete (LOOP_VINFO_PEELING_HTAB (loop_vinfo));
|
||||
if (LOOP_VINFO_PEELING_HTAB (loop_vinfo).is_created ())
|
||||
LOOP_VINFO_PEELING_HTAB (loop_vinfo).dispose ();
|
||||
|
||||
destroy_cost_data (LOOP_VINFO_TARGET_COST_DATA (loop_vinfo));
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
#include "tree-data-ref.h"
|
||||
#include "target.h"
|
||||
#include "hash-table.h"
|
||||
|
||||
typedef source_location LOC;
|
||||
#define UNKNOWN_LOC UNKNOWN_LOCATION
|
||||
|
@ -189,6 +190,30 @@ typedef struct _vect_peel_extended_info
|
|||
stmt_vector_for_cost body_cost_vec;
|
||||
} *vect_peel_extended_info;
|
||||
|
||||
|
||||
/* Peeling hashtable helpers. */
|
||||
|
||||
struct peel_info_hasher : typed_free_remove <_vect_peel_info>
|
||||
{
|
||||
typedef _vect_peel_info value_type;
|
||||
typedef _vect_peel_info compare_type;
|
||||
static inline hashval_t hash (const value_type *);
|
||||
static inline bool equal (const value_type *, const compare_type *);
|
||||
};
|
||||
|
||||
inline hashval_t
|
||||
peel_info_hasher::hash (const value_type *peel_info)
|
||||
{
|
||||
return (hashval_t) peel_info->npeel;
|
||||
}
|
||||
|
||||
inline bool
|
||||
peel_info_hasher::equal (const value_type *a, const compare_type *b)
|
||||
{
|
||||
return (a->npeel == b->npeel);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Info on vectorized loops. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
@ -273,7 +298,7 @@ typedef struct _loop_vec_info {
|
|||
vec<gimple> reduction_chains;
|
||||
|
||||
/* Hash table used to choose the best peeling option. */
|
||||
htab_t peeling_htab;
|
||||
hash_table <peel_info_hasher> peeling_htab;
|
||||
|
||||
/* Cost data used by the target cost model. */
|
||||
void *target_cost_data;
|
||||
|
|
Loading…
Reference in New Issue