110d565efSmrg /* SparseSet implementation.
2*ec02198aSmrg    Copyright (C) 2007-2020 Free Software Foundation, Inc.
310d565efSmrg    Contributed by Peter Bergner <bergner@vnet.ibm.com>
410d565efSmrg 
510d565efSmrg This file is part of GCC.
610d565efSmrg 
710d565efSmrg GCC is free software; you can redistribute it and/or modify it under
810d565efSmrg the terms of the GNU General Public License as published by the Free
910d565efSmrg Software Foundation; either version 3, or (at your option) any later
1010d565efSmrg version.
1110d565efSmrg 
1210d565efSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1310d565efSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1410d565efSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1510d565efSmrg for more details.
1610d565efSmrg 
1710d565efSmrg You should have received a copy of the GNU General Public License
1810d565efSmrg along with GCC; see the file COPYING3.  If not see
1910d565efSmrg <http://www.gnu.org/licenses/>.  */
2010d565efSmrg 
2110d565efSmrg #ifndef GCC_SPARSESET_H
2210d565efSmrg #define GCC_SPARSESET_H
2310d565efSmrg 
2410d565efSmrg /* Implementation of the Briggs and Torczon sparse set representation.
2510d565efSmrg    The sparse set representation was first published in:
2610d565efSmrg 
2710d565efSmrg    "An Efficient Representation for Sparse Sets",
2810d565efSmrg    ACM LOPLAS, Vol. 2, Nos. 1-4, March-December 1993, Pages 59-69.
2910d565efSmrg 
3010d565efSmrg    The sparse set representation is suitable for integer sets with a
3110d565efSmrg    fixed-size universe.  Two vectors are used to store the members of
3210d565efSmrg    the set.  If an element I is in the set, then sparse[I] is the
3310d565efSmrg    index of I in the dense vector, and dense[sparse[I]] == I.  The dense
3410d565efSmrg    vector works like a stack.  The size of the stack is the cardinality
3510d565efSmrg    of the set.
3610d565efSmrg 
3710d565efSmrg    The following operations can be performed in O(1) time:
3810d565efSmrg 
3910d565efSmrg      * clear			: sparseset_clear
4010d565efSmrg      * cardinality		: sparseset_cardinality
4110d565efSmrg      * set_size			: sparseset_size
4210d565efSmrg      * member_p			: sparseset_bit_p
4310d565efSmrg      * add_member		: sparseset_set_bit
4410d565efSmrg      * remove_member		: sparseset_clear_bit
4510d565efSmrg      * choose_one		: sparseset_pop
4610d565efSmrg 
4710d565efSmrg    Additionally, the sparse set representation supports enumeration of
4810d565efSmrg    the members in O(N) time, where n is the number of members in the set.
4910d565efSmrg    The members of the set are stored cache-friendly in the dense vector.
5010d565efSmrg    This makes it a competitive choice for iterating over relatively sparse
5110d565efSmrg    sets requiring operations:
5210d565efSmrg 
5310d565efSmrg      * forall			: EXECUTE_IF_SET_IN_SPARSESET
5410d565efSmrg      * set_copy			: sparseset_copy
5510d565efSmrg      * set_intersection		: sparseset_and
5610d565efSmrg      * set_union		: sparseset_ior
5710d565efSmrg      * set_difference		: sparseset_and_compl
5810d565efSmrg      * set_disjuction		: (not implemented)
5910d565efSmrg      * set_compare		: sparseset_equal_p
6010d565efSmrg 
6110d565efSmrg    NB: It is OK to use remove_member during EXECUTE_IF_SET_IN_SPARSESET.
6210d565efSmrg    The iterator is updated for it.
6310d565efSmrg 
6410d565efSmrg    Based on the efficiency of these operations, this representation of
6510d565efSmrg    sparse sets will often be superior to alternatives such as simple
6610d565efSmrg    bitmaps, linked-list bitmaps, array bitmaps, balanced binary trees,
6710d565efSmrg    hash tables, linked lists, etc., if the set is sufficiently sparse.
6810d565efSmrg    In the LOPLAS paper the cut-off point where sparse sets became faster
6910d565efSmrg    than simple bitmaps (see sbitmap.h) when N / U < 64 (where U is the
7010d565efSmrg    size of the universe of the set).
7110d565efSmrg 
7210d565efSmrg    Because the set universe is fixed, the set cannot be resized.  For
7310d565efSmrg    sparse sets with initially unknown size, linked-list bitmaps are a
7410d565efSmrg    better choice, see bitmap.h.
7510d565efSmrg 
7610d565efSmrg    Sparse sets storage requirements are relatively large: O(U) with a
7710d565efSmrg    larger constant than sbitmaps (if the storage requirement for an
7810d565efSmrg    sbitmap with universe U is S, then the storage required for a sparse
7910d565efSmrg    set for the same universe are 2*HOST_BITS_PER_WIDEST_FAST_INT * S).
8010d565efSmrg    Accessing the sparse vector is not very cache-friendly, but iterating
8110d565efSmrg    over the members in the set is cache-friendly because only the dense
8210d565efSmrg    vector is used.  */
8310d565efSmrg 
8410d565efSmrg /* Data Structure used for the SparseSet representation.  */
8510d565efSmrg 
8610d565efSmrg #define SPARSESET_ELT_BITS ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT)
8710d565efSmrg #define SPARSESET_ELT_TYPE unsigned HOST_WIDEST_FAST_INT
8810d565efSmrg 
8910d565efSmrg typedef struct sparseset_def
9010d565efSmrg {
9110d565efSmrg   SPARSESET_ELT_TYPE *dense;	/* Dense array.  */
9210d565efSmrg   SPARSESET_ELT_TYPE *sparse;	/* Sparse array.  */
9310d565efSmrg   SPARSESET_ELT_TYPE members;	/* Number of elements.  */
9410d565efSmrg   SPARSESET_ELT_TYPE size;	/* Maximum number of elements.  */
9510d565efSmrg   SPARSESET_ELT_TYPE iter;	/* Iterator index.  */
9610d565efSmrg   unsigned char iter_inc;	/* Iteration increment amount.  */
9710d565efSmrg   bool iterating;
9810d565efSmrg   SPARSESET_ELT_TYPE elms[2];   /* Combined dense and sparse arrays.  */
9910d565efSmrg } *sparseset;
10010d565efSmrg 
10110d565efSmrg #define sparseset_free(MAP)  free(MAP)
10210d565efSmrg extern sparseset sparseset_alloc (SPARSESET_ELT_TYPE n_elms);
10310d565efSmrg extern void sparseset_clear_bit (sparseset, SPARSESET_ELT_TYPE);
10410d565efSmrg extern void sparseset_copy (sparseset, sparseset);
10510d565efSmrg extern void sparseset_and (sparseset, sparseset, sparseset);
10610d565efSmrg extern void sparseset_and_compl (sparseset, sparseset, sparseset);
10710d565efSmrg extern void sparseset_ior (sparseset, sparseset, sparseset);
10810d565efSmrg extern bool sparseset_equal_p (sparseset, sparseset);
10910d565efSmrg 
11010d565efSmrg /* Operation: S = {}
11110d565efSmrg    Clear the set of all elements.  */
11210d565efSmrg 
11310d565efSmrg static inline void
sparseset_clear(sparseset s)11410d565efSmrg sparseset_clear (sparseset s)
11510d565efSmrg {
11610d565efSmrg   s->members = 0;
11710d565efSmrg   s->iterating = false;
11810d565efSmrg }
11910d565efSmrg 
12010d565efSmrg /* Return the number of elements currently in the set.  */
12110d565efSmrg 
12210d565efSmrg static inline SPARSESET_ELT_TYPE
sparseset_cardinality(sparseset s)12310d565efSmrg sparseset_cardinality (sparseset s)
12410d565efSmrg {
12510d565efSmrg   return s->members;
12610d565efSmrg }
12710d565efSmrg 
12810d565efSmrg /* Return the maximum number of elements this set can hold.  */
12910d565efSmrg 
13010d565efSmrg static inline SPARSESET_ELT_TYPE
sparseset_size(sparseset s)13110d565efSmrg sparseset_size (sparseset s)
13210d565efSmrg {
13310d565efSmrg   return s->size;
13410d565efSmrg }
13510d565efSmrg 
13610d565efSmrg /* Return true if e is a member of the set S, otherwise return false.  */
13710d565efSmrg 
13810d565efSmrg static inline bool
sparseset_bit_p(sparseset s,SPARSESET_ELT_TYPE e)13910d565efSmrg sparseset_bit_p (sparseset s, SPARSESET_ELT_TYPE e)
14010d565efSmrg {
14110d565efSmrg   SPARSESET_ELT_TYPE idx;
14210d565efSmrg 
14310d565efSmrg   gcc_checking_assert (e < s->size);
14410d565efSmrg 
14510d565efSmrg   idx = s->sparse[e];
14610d565efSmrg 
14710d565efSmrg   return idx < s->members && s->dense[idx] == e;
14810d565efSmrg }
14910d565efSmrg 
15010d565efSmrg /* Low level insertion routine not meant for use outside of sparseset.[ch].
15110d565efSmrg    Assumes E is valid and not already a member of the set S.  */
15210d565efSmrg 
15310d565efSmrg static inline void
sparseset_insert_bit(sparseset s,SPARSESET_ELT_TYPE e,SPARSESET_ELT_TYPE idx)15410d565efSmrg sparseset_insert_bit (sparseset s, SPARSESET_ELT_TYPE e, SPARSESET_ELT_TYPE idx)
15510d565efSmrg {
15610d565efSmrg   s->sparse[e] = idx;
15710d565efSmrg   s->dense[idx] = e;
15810d565efSmrg }
15910d565efSmrg 
16010d565efSmrg /* Operation: S = S + {e}
16110d565efSmrg    Insert E into the set S, if it isn't already a member.  */
16210d565efSmrg 
16310d565efSmrg static inline void
sparseset_set_bit(sparseset s,SPARSESET_ELT_TYPE e)16410d565efSmrg sparseset_set_bit (sparseset s, SPARSESET_ELT_TYPE e)
16510d565efSmrg {
16610d565efSmrg   if (!sparseset_bit_p (s, e))
16710d565efSmrg     sparseset_insert_bit (s, e, s->members++);
16810d565efSmrg }
16910d565efSmrg 
17010d565efSmrg /* Return and remove the last member added to the set S.  */
17110d565efSmrg 
17210d565efSmrg static inline SPARSESET_ELT_TYPE
sparseset_pop(sparseset s)17310d565efSmrg sparseset_pop (sparseset s)
17410d565efSmrg {
17510d565efSmrg   SPARSESET_ELT_TYPE mem = s->members;
17610d565efSmrg 
17710d565efSmrg   gcc_checking_assert (mem != 0);
17810d565efSmrg 
17910d565efSmrg   s->members = mem - 1;
18010d565efSmrg   return s->dense[s->members];
18110d565efSmrg }
18210d565efSmrg 
18310d565efSmrg static inline void
sparseset_iter_init(sparseset s)18410d565efSmrg sparseset_iter_init (sparseset s)
18510d565efSmrg {
18610d565efSmrg   s->iter = 0;
18710d565efSmrg   s->iter_inc = 1;
18810d565efSmrg   s->iterating = true;
18910d565efSmrg }
19010d565efSmrg 
19110d565efSmrg static inline bool
sparseset_iter_p(sparseset s)19210d565efSmrg sparseset_iter_p (sparseset s)
19310d565efSmrg {
19410d565efSmrg   if (s->iterating && s->iter < s->members)
19510d565efSmrg     return true;
19610d565efSmrg   else
19710d565efSmrg     return s->iterating = false;
19810d565efSmrg }
19910d565efSmrg 
20010d565efSmrg static inline SPARSESET_ELT_TYPE
sparseset_iter_elm(sparseset s)20110d565efSmrg sparseset_iter_elm (sparseset s)
20210d565efSmrg {
20310d565efSmrg   return s->dense[s->iter];
20410d565efSmrg }
20510d565efSmrg 
20610d565efSmrg static inline void
sparseset_iter_next(sparseset s)20710d565efSmrg sparseset_iter_next (sparseset s)
20810d565efSmrg {
20910d565efSmrg   s->iter += s->iter_inc;
21010d565efSmrg   s->iter_inc = 1;
21110d565efSmrg }
21210d565efSmrg 
21310d565efSmrg #define EXECUTE_IF_SET_IN_SPARSESET(SPARSESET, ITER)			\
21410d565efSmrg   for (sparseset_iter_init (SPARSESET);					\
21510d565efSmrg        sparseset_iter_p (SPARSESET)					\
21610d565efSmrg        && (((ITER) = sparseset_iter_elm (SPARSESET)) || 1);		\
21710d565efSmrg        sparseset_iter_next (SPARSESET))
21810d565efSmrg 
21910d565efSmrg #endif /* GCC_SPARSESET_H */
220