summaryrefslogtreecommitdiff
path: root/gcc/sparseset.c
diff options
context:
space:
mode:
authorbergner <bergner@138bc75d-0d04-0410-961f-82ee72b054a4>2007-10-05 17:55:18 +0000
committerbergner <bergner@138bc75d-0d04-0410-961f-82ee72b054a4>2007-10-05 17:55:18 +0000
commit981db194768f6990aef28c6ea50b2f37012dd92d (patch)
tree2e03ef60b9463aa8d6f1cf89bba364c677a542ef /gcc/sparseset.c
parent0fd56ba63aedc691ef1dae70f621639b77274b91 (diff)
downloadgcc-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.c232
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;
+}
+