/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_hash.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2008-2009 Katholieke Universiteit Leuven |
3 | | * |
4 | | * Use of this software is governed by the MIT license |
5 | | * |
6 | | * Written by Sven Verdoolaege, K.U.Leuven, Departement |
7 | | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium |
8 | | */ |
9 | | |
10 | | #include <stdlib.h> |
11 | | #include <isl_hash_private.h> |
12 | | #include <isl/ctx.h> |
13 | | #include "isl_config.h" |
14 | | |
15 | | uint32_t isl_hash_string(uint32_t hash, const char *s) |
16 | 160k | { |
17 | 1.56M | for (; *s; s++1.40M ) |
18 | 1.40M | isl_hash_byte(hash, *s); |
19 | 160k | return hash; |
20 | 160k | } |
21 | | |
22 | | uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len) |
23 | 11.4k | { |
24 | 11.4k | int i; |
25 | 11.4k | const char *s = p; |
26 | 103k | for (i = 0; i < len; ++i91.9k ) |
27 | 91.9k | isl_hash_byte(hash, s[i]); |
28 | 11.4k | return hash; |
29 | 11.4k | } |
30 | | |
31 | | static unsigned int round_up(unsigned int v) |
32 | 466k | { |
33 | 466k | int old_v = v; |
34 | 466k | |
35 | 1.58M | while (v) { |
36 | 1.11M | old_v = v; |
37 | 1.11M | v ^= v & -v; |
38 | 1.11M | } |
39 | 466k | return old_v << 1; |
40 | 466k | } |
41 | | |
42 | | int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table, |
43 | | int min_size) |
44 | 466k | { |
45 | 466k | size_t size; |
46 | 466k | |
47 | 466k | if (!table) |
48 | 0 | return -1; |
49 | 466k | |
50 | 466k | if (min_size < 2) |
51 | 170k | min_size = 2; |
52 | 466k | table->bits = ffs(round_up(4 * (min_size + 1) / 3 - 1)) - 1; |
53 | 466k | table->n = 0; |
54 | 466k | |
55 | 466k | size = 1 << table->bits; |
56 | 466k | table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry, |
57 | 466k | size); |
58 | 466k | if (!table->entries) |
59 | 8 | return -1; |
60 | 466k | |
61 | 466k | return 0; |
62 | 466k | } |
63 | | |
64 | | /* Dummy comparison function that always returns false. |
65 | | */ |
66 | | static int no(const void *entry, const void *val) |
67 | 111k | { |
68 | 111k | return 0; |
69 | 111k | } |
70 | | |
71 | | /* Extend "table" to twice its size. |
72 | | * Return 0 on success and -1 on error. |
73 | | * |
74 | | * We reuse isl_hash_table_find to create entries in the extended table. |
75 | | * Since all entries in the original table are assumed to be different, |
76 | | * there is no need to compare them against each other. |
77 | | */ |
78 | | static int grow_table(struct isl_ctx *ctx, struct isl_hash_table *table) |
79 | 4.84k | { |
80 | 4.84k | int n; |
81 | 4.84k | size_t old_size, size; |
82 | 4.84k | struct isl_hash_table_entry *entries; |
83 | 4.84k | uint32_t h; |
84 | 4.84k | |
85 | 4.84k | entries = table->entries; |
86 | 4.84k | old_size = 1 << table->bits; |
87 | 4.84k | size = 2 * old_size; |
88 | 4.84k | table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry, |
89 | 4.84k | size); |
90 | 4.84k | if (!table->entries) { |
91 | 0 | table->entries = entries; |
92 | 0 | return -1; |
93 | 0 | } |
94 | 4.84k | |
95 | 4.84k | n = table->n; |
96 | 4.84k | table->n = 0; |
97 | 4.84k | table->bits++; |
98 | 4.84k | |
99 | 50.6k | for (h = 0; h < old_size; ++h45.8k ) { |
100 | 45.8k | struct isl_hash_table_entry *entry; |
101 | 45.8k | |
102 | 45.8k | if (!entries[h].data) |
103 | 11.4k | continue; |
104 | 34.3k | |
105 | 34.3k | entry = isl_hash_table_find(ctx, table, entries[h].hash, |
106 | 34.3k | &no, NULL, 1); |
107 | 34.3k | if (!entry) { |
108 | 0 | table->bits--; |
109 | 0 | free(table->entries); |
110 | 0 | table->entries = entries; |
111 | 0 | table->n = n; |
112 | 0 | return -1; |
113 | 0 | } |
114 | 34.3k | |
115 | 34.3k | *entry = entries[h]; |
116 | 34.3k | } |
117 | 4.84k | |
118 | 4.84k | free(entries); |
119 | 4.84k | |
120 | 4.84k | return 0; |
121 | 4.84k | } |
122 | | |
123 | | struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size) |
124 | 97.4k | { |
125 | 97.4k | struct isl_hash_table *table = NULL; |
126 | 97.4k | |
127 | 97.4k | table = isl_alloc_type(ctx, struct isl_hash_table); |
128 | 97.4k | if (isl_hash_table_init(ctx, table, min_size)) |
129 | 0 | goto error; |
130 | 97.4k | return table; |
131 | 0 | error: |
132 | 0 | isl_hash_table_free(ctx, table); |
133 | 0 | return NULL; |
134 | 97.4k | } |
135 | | |
136 | | void isl_hash_table_clear(struct isl_hash_table *table) |
137 | 466k | { |
138 | 466k | if (!table) |
139 | 0 | return; |
140 | 466k | free(table->entries); |
141 | 466k | } |
142 | | |
143 | | void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table) |
144 | 97.5k | { |
145 | 97.5k | if (!table) |
146 | 108 | return; |
147 | 97.4k | isl_hash_table_clear(table); |
148 | 97.4k | free(table); |
149 | 97.4k | } |
150 | | |
151 | | /* A dummy entry that can be used to make a distinction between |
152 | | * a missing entry and an error condition. |
153 | | * It is used by isl_union_*_find_part_entry. |
154 | | */ |
155 | | static struct isl_hash_table_entry none = { 0, NULL }; |
156 | | struct isl_hash_table_entry *isl_hash_table_entry_none = &none; |
157 | | |
158 | | struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx, |
159 | | struct isl_hash_table *table, |
160 | | uint32_t key_hash, |
161 | | int (*eq)(const void *entry, const void *val), |
162 | | const void *val, int reserve) |
163 | 4.36M | { |
164 | 4.36M | size_t size; |
165 | 4.36M | uint32_t h, key_bits; |
166 | 4.36M | |
167 | 4.36M | key_bits = isl_hash_bits(key_hash, table->bits); |
168 | 4.36M | size = 1 << table->bits; |
169 | 5.65M | for (h = key_bits; table->entries[h].data; h = (h+1) % size1.29M ) |
170 | 3.64M | if (table->entries[h].hash == key_hash && |
171 | 3.64M | eq(table->entries[h].data, val)2.75M ) |
172 | 2.35M | return &table->entries[h]; |
173 | 4.36M | |
174 | 4.36M | if (2.00M !reserve2.00M ) |
175 | 385k | return NULL; |
176 | 1.61M | |
177 | 1.61M | if (4 * table->n >= 3 * size) { |
178 | 4.84k | if (grow_table(ctx, table) < 0) |
179 | 0 | return NULL; |
180 | 4.84k | return isl_hash_table_find(ctx, table, key_hash, eq, val, 1); |
181 | 4.84k | } |
182 | 1.61M | |
183 | 1.61M | table->n++; |
184 | 1.61M | table->entries[h].hash = key_hash; |
185 | 1.61M | |
186 | 1.61M | return &table->entries[h]; |
187 | 1.61M | } |
188 | | |
189 | | isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table, |
190 | | isl_stat (*fn)(void **entry, void *user), void *user) |
191 | 955k | { |
192 | 955k | size_t size; |
193 | 955k | uint32_t h; |
194 | 955k | |
195 | 955k | if (!table->entries) |
196 | 8 | return isl_stat_error; |
197 | 955k | |
198 | 955k | size = 1 << table->bits; |
199 | 16.9M | for (h = 0; h < size; ++ h16.0M ) |
200 | 16.1M | if (table->entries[h].data && |
201 | 16.1M | fn(&table->entries[h].data, user) < 01.23M ) |
202 | 101k | return isl_stat_error; |
203 | 955k | |
204 | 955k | return isl_stat_ok853k ; |
205 | 955k | } |
206 | | |
207 | | void isl_hash_table_remove(struct isl_ctx *ctx, |
208 | | struct isl_hash_table *table, |
209 | | struct isl_hash_table_entry *entry) |
210 | 75.7k | { |
211 | 75.7k | int h, h2; |
212 | 75.7k | size_t size; |
213 | 75.7k | |
214 | 75.7k | if (!table || !entry) |
215 | 0 | return; |
216 | 75.7k | |
217 | 75.7k | size = 1 << table->bits; |
218 | 75.7k | h = entry - table->entries; |
219 | 75.7k | isl_assert(ctx, h >= 0 && h < size, return); |
220 | 75.7k | |
221 | 356k | for (h2 = h+1; 75.7k table->entries[h2 % size].data; h2++281k ) { |
222 | 281k | uint32_t bits = isl_hash_bits(table->entries[h2 % size].hash, |
223 | 281k | table->bits); |
224 | 281k | uint32_t offset = (size + bits - (h+1)) % size; |
225 | 281k | if (offset <= h2 - (h+1)) |
226 | 52.6k | continue; |
227 | 228k | *entry = table->entries[h2 % size]; |
228 | 228k | h = h2; |
229 | 228k | entry = &table->entries[h % size]; |
230 | 228k | } |
231 | 75.7k | |
232 | 75.7k | entry->hash = 0; |
233 | 75.7k | entry->data = NULL; |
234 | 75.7k | table->n--; |
235 | 75.7k | } |