diff options
author | bergner <bergner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-05 17:55:18 +0000 |
---|---|---|
committer | bergner <bergner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-05 17:55:18 +0000 |
commit | 981db194768f6990aef28c6ea50b2f37012dd92d (patch) | |
tree | 2e03ef60b9463aa8d6f1cf89bba364c677a542ef /gcc/sparseset.c | |
parent | 0fd56ba63aedc691ef1dae70f621639b77274b91 (diff) | |
download | gcc-981db194768f6990aef28c6ea50b2f37012dd92d.tar.gz |
* ra-conflict.c: Include "sparseset.h".
(conflicts): Change to HOST_WIDEST_FAST_INT.
(allocnos_live): Redefine variable as a sparseset.
(SET_ALLOCNO_LIVE, CLEAR_ALLOCNO_LIVE, GET_ALLOCNO_LIVE): Delete macros.
(allocno_row_words): Removed global variable.
(partial_bitnum, max_bitnum, adjacency_pool, adjacency): New variables.
(CONFLICT_BITNUM, CONFLICT_BITNUM_FAST): New defines.
(conflict_p, set_conflict_p, set_conflicts_p): New functions.
(record_one_conflict_between_regnos): Cache allocno values and reuse.
Use set_conflict_p.
(record_one_conflict): Update uses of allocnos_live to use
the sparseset routines. Use set_conflicts_p.
(mark_reg_store): Likewise.
(set_reg_in_live): Likewise.
(global_conflicts): Update uses of allocnos_live.
Use the new adjacency list to visit an allocno's neighbors
rather than iterating over all possible allocnos.
Call set_conflicts_p to setup conflicts rather than adding
them manually.
* global.c: Comments updated.
(CONFLICTP): Delete define.
(regno_compare): New function. Add prototype.
(global_alloc): Sort the allocno to regno mapping according to
which basic blocks the regnos are referenced in. Modify the
conflict bit matrix to a compressed triangular bitmatrix.
Only allocate the conflict bit matrix and adjacency lists if
we are actually going to allocate something.
(expand_preferences): Use conflict_p. Update uses of allocnos_live.
(prune_preferences): Use the FOR_EACH_CONFLICT macro to visit an
allocno's neighbors rather than iterating over all possible allocnos.
(mirror_conflicts): Removed function.
(dump_conflicts): Iterate over regnos rather than allocnos so
that all dump output will be sorted by regno number.
Use the FOR_EACH_CONFLICT macro.
* ra.h: Comments updated.
(conflicts): Update prototype to HOST_WIDEST_FAST_INT.
(partial_bitnum, max_bitnum, adjacency, adjacency_pool): Add prototypes.
(ADJACENCY_VEC_LENGTH, FOR_EACH_CONFLICT): New defines.
(adjacency_list_d, adjacency_iterator_d): New types.
(add_neighbor, adjacency_iter_init, adjacency_iter_done,
adjacency_iter_next, regno_basic_block): New static inline functions.
(EXECUTE_IF_SET_IN_ALLOCNO_SET): Removed define.
(conflict_p): Add function prototype.
* sparseset.h, sparseset.c: New files.
* Makefile.in (OBJS-common): Add sparseset.o.
(sparseset.o): New rule.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129037 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/sparseset.c')
-rw-r--r-- | gcc/sparseset.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/gcc/sparseset.c b/gcc/sparseset.c new file mode 100644 index 00000000000..8d7cd9373bd --- /dev/null +++ b/gcc/sparseset.c @@ -0,0 +1,232 @@ +/* SparseSet implementation. + Copyright (C) 2007 Free Software Foundation, Inc. + Contributed by Peter Bergner <bergner@vnet.ibm.com> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "libiberty.h" +#include "sparseset.h" + + +/* Allocate and clear a n_elms SparseSet. */ + +sparseset +sparseset_alloc (SPARSESET_ELT_TYPE n_elms) +{ + unsigned int n_bytes = sizeof (struct sparseset_def) + + ((n_elms - 1) * 2 * sizeof (SPARSESET_ELT_TYPE)); + + sparseset set = (sparseset) xmalloc (n_bytes); + set->dense = &(set->elms[0]); + set->sparse = &(set->elms[n_elms]); + set->size = n_elms; + sparseset_clear (set); + return set; +} + +/* Low level routine not meant for use outside of sparseset.[ch]. + Assumes idx1 < s->members and idx2 < s->members. */ + +static inline void +sparseset_swap (sparseset s, SPARSESET_ELT_TYPE idx1, SPARSESET_ELT_TYPE idx2) +{ + SPARSESET_ELT_TYPE tmp = s->dense[idx2]; + sparseset_insert_bit (s, s->dense[idx1], idx2); + sparseset_insert_bit (s, tmp, idx1); +} + +/* Operation: S = S - {e} + Delete e from the set S if it is a member of S. */ + +void +sparseset_clear_bit (sparseset s, SPARSESET_ELT_TYPE e) +{ + if (sparseset_bit_p (s, e)) + { + SPARSESET_ELT_TYPE idx = s->sparse[e]; + SPARSESET_ELT_TYPE iter = s->iter; + SPARSESET_ELT_TYPE mem = s->members - 1; + + /* If we are iterating over this set and we want to delete a + member we've already visited, then we swap the element we + want to delete with the element at the current iteration + index so that it plays well together with the code below + that actually removes the element. */ + if (s->iterating && idx <= iter) + { + if (idx < iter) + { + sparseset_swap (s, idx, iter); + idx = iter; + } + s->iter_inc = 0; + } + + /* Replace the element we want to delete with the last element + in the dense array and then decrement s->members, effectively + removing the element we want to delete. */ + sparseset_insert_bit (s, s->dense[mem], idx); + s->members = mem; + } +} + +/* Operation: D = S + Restrictions: none. */ + +void +sparseset_copy (sparseset d, sparseset s) +{ + SPARSESET_ELT_TYPE i; + + if (d == s) + return; + + sparseset_clear (d); + for (i = 0; i < s->members; i++) + sparseset_insert_bit (d, s->dense[i], i); + d->members = s->members; +} + +/* Operation: D = A & B. + Restrictions: none. */ + +void +sparseset_and (sparseset d, sparseset a, sparseset b) +{ + SPARSESET_ELT_TYPE e; + + if (a == b) + { + if (d != a) + sparseset_copy (d, a); + return; + } + + if (d == a || d == b) + { + sparseset s = (d == a) ? b : a; + + EXECUTE_IF_SET_IN_SPARSESET (d, e) + if (!sparseset_bit_p (s, e)) + sparseset_clear_bit (d, e); + } + else + { + sparseset sml, lrg; + + if (sparseset_cardinality (a) < sparseset_cardinality (b)) + { + sml = a; + lrg = b; + } + else + { + sml = b; + lrg = a; + } + + sparseset_clear (d); + EXECUTE_IF_SET_IN_SPARSESET (sml, e) + if (sparseset_bit_p (lrg, e)) + sparseset_set_bit (d, e); + } +} + +/* Operation: D = A & ~B. + Restrictions: D != B, unless D == A == B. */ + +void +sparseset_and_compl (sparseset d, sparseset a, sparseset b) +{ + SPARSESET_ELT_TYPE e; + + if (a == b) + { + sparseset_clear (d); + return; + } + + gcc_assert (d != b); + + if (d == a) + { + if (sparseset_cardinality (d) < sparseset_cardinality (b)) + { + EXECUTE_IF_SET_IN_SPARSESET (d, e) + if (sparseset_bit_p (b, e)) + sparseset_clear_bit (d, e); + } + else + { + EXECUTE_IF_SET_IN_SPARSESET (b, e) + sparseset_clear_bit (d, e); + } + } + else + { + sparseset_clear (d); + EXECUTE_IF_SET_IN_SPARSESET (a, e) + if (!sparseset_bit_p (b, e)) + sparseset_set_bit (d, e); + } +} + +/* Operation: D = A | B. + Restrictions: none. */ + +void +sparseset_ior (sparseset d, sparseset a, sparseset b) +{ + SPARSESET_ELT_TYPE e; + + if (a == b) + sparseset_copy (d, a); + else if (d == b) + { + EXECUTE_IF_SET_IN_SPARSESET (a, e) + sparseset_set_bit (d, e); + } + else + { + if (d != a) + sparseset_copy (d, a); + EXECUTE_IF_SET_IN_SPARSESET (b, e) + sparseset_set_bit (d, e); + } +} + +/* Operation: A == B + Restrictions: none. */ + +bool +sparseset_equal_p (sparseset a, sparseset b) +{ + SPARSESET_ELT_TYPE e; + + if (a == b) + return true; + + if (sparseset_cardinality (a) != sparseset_cardinality (b)) + return false; + + EXECUTE_IF_SET_IN_SPARSESET (a, e) + if (!sparseset_bit_p (b, e)) + return false; + + return true; +} + |