PR target/16286
[official-gcc.git] / gcc / pointer-set.c
blobb0f04ff3aa3d6927151641a8afaf7dd57433a81f
1 /* Set operations on pointers
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "pointer-set.h"
25 /* A pointer sets is represented as a simple open-addressing hash
26 table. Simplifications: The hash code is based on the value of the
27 pointer, not what it points to. The number of buckets is always a
28 power of 2. Null pointers are a reserved value. Deletion is not
29 supported. There is no mechanism for user control of hash
30 function, equality comparison, initial size, or resizing policy.
33 struct pointer_set_t
35 size_t log_slots;
36 size_t n_slots; /* n_slots = 2^log_slots */
37 size_t n_elements;
39 void **slots;
42 /* Use the multiplicative method, as described in Knuth 6.4, to obtain
43 a hash code for P in the range [0, MAX). MAX == 2^LOGMAX.
45 Summary of this method: Multiply p by some number A that's
46 relatively prime to 2^sizeof(size_t). The result is two words.
47 Discard the most significant word, and return the most significant
48 N bits of the least significant word. As suggested by Knuth, our
49 choice for A is the integer part of (ULONG_MAX + 1.0) / phi, where phi
50 is the golden ratio.
52 We don't need to do anything special for full-width multiplication
53 because we're only interested in the least significant word of the
54 product, and unsigned arithmetic in C is modulo the word size. */
56 static inline size_t
57 hash1 (const void *p, unsigned long max, unsigned long logmax)
59 #if HOST_BITS_PER_LONG == 32
60 const unsigned long A = 0x9e3779b9u;
61 #elif HOST_BITS_PER_LONG == 64
62 const unsigned long A = 0x9e3779b97f4a7c16ul;
63 #else
64 const unsigned long A
65 = (ULONG_MAX + 1.0L) * 0.6180339887498948482045868343656381177203L;
66 #endif
67 const unsigned long shift = HOST_BITS_PER_LONG - logmax;
69 return ((A * (unsigned long) p) >> shift) & (max - 1);
72 /* Allocate an empty pointer set. */
73 struct pointer_set_t *
74 pointer_set_create (void)
76 struct pointer_set_t *result = XNEW (struct pointer_set_t);
78 result->n_elements = 0;
79 result->log_slots = 8;
80 result->n_slots = (size_t) 1 << result->log_slots;
82 result->slots = XCNEWVEC (void *, result->n_slots);
83 return result;
86 /* Reclaims all memory associated with PSET. */
87 void pointer_set_destroy (struct pointer_set_t *pset)
89 XDELETEVEC (pset->slots);
90 XDELETE (pset);
93 /* Returns nonzero if PSET contains P. P must be nonnull.
95 Collisions are resolved by linear probing. More complicated
96 collision management schemes are only useful when the load factor
97 significantly exceeds 0.5, and we never let that happen. */
98 int
99 pointer_set_contains (struct pointer_set_t *pset, void *p)
101 size_t n = hash1 (p, pset->n_slots, pset->log_slots);
103 while (true)
105 if (pset->slots[n] == p)
106 return 1;
107 else if (pset->slots[n] == 0)
108 return 0;
109 else
111 ++n;
112 if (n == pset->n_slots)
113 n = 0;
118 /* Subroutine of pointer_set_insert. Inserts P into an empty
119 element of SLOTS, an array of length N_SLOTS. Returns nonzero
120 if P was already present in N_SLOTS. */
121 static int
122 insert_aux (void *p, void **slots, size_t n_slots, size_t log_slots)
124 size_t n = hash1 (p, n_slots, log_slots);
125 while (true)
127 if (slots[n] == p)
128 return 1;
129 else if (slots[n] == 0)
131 slots[n] = p;
132 return 0;
134 else
136 ++n;
137 if (n == n_slots)
138 n = 0;
143 /* Inserts P into PSET if it wasn't already there. Returns nonzero
144 if it was already there. P must be nonnull. */
146 pointer_set_insert (struct pointer_set_t *pset, void *p)
148 if (insert_aux (p, pset->slots, pset->n_slots, pset->log_slots))
149 return 1;
151 /* We've inserted a new element. Expand the table if necessary to keep
152 the load factor small. */
153 ++pset->n_elements;
154 if (pset->n_elements > pset->n_slots / 4)
156 size_t new_log_slots = pset->log_slots + 1;
157 size_t new_n_slots = pset->n_slots * 2;
158 void **new_slots = XCNEWVEC (void *, new_n_slots);
159 size_t i;
161 for (i = 0; i < pset->n_slots; ++i)
163 if (pset->slots[i])
164 insert_aux (pset->slots[i], new_slots, new_n_slots, new_log_slots);
167 XDELETEVEC (pset->slots);
168 pset->n_slots = new_n_slots;
169 pset->log_slots = new_log_slots;
170 pset->slots = new_slots;
173 return 0;