isl_union_single.c revision 1.1 1 1.1 mrg /*
2 1.1 mrg * Copyright 2010 INRIA Saclay
3 1.1 mrg * Copyright 2013 Ecole Normale Superieure
4 1.1 mrg *
5 1.1 mrg * Use of this software is governed by the MIT license
6 1.1 mrg *
7 1.1 mrg * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
8 1.1 mrg * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
9 1.1 mrg * 91893 Orsay, France
10 1.1 mrg * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
11 1.1 mrg */
12 1.1 mrg
13 1.1 mrg #include <isl/hash.h>
14 1.1 mrg #include <isl_union_macro.h>
15 1.1 mrg
16 1.1 mrg /* A union of expressions defined over different domain spaces.
17 1.1 mrg * "space" describes the parameters.
18 1.1 mrg * The entries of "table" are keyed on the domain space of the entry
19 1.1 mrg * (ignoring parameters).
20 1.1 mrg */
21 1.1 mrg struct UNION {
22 1.1 mrg int ref;
23 1.1 mrg #ifdef HAS_TYPE
24 1.1 mrg enum isl_fold type;
25 1.1 mrg #endif
26 1.1 mrg isl_space *space;
27 1.1 mrg
28 1.1 mrg struct isl_hash_table table;
29 1.1 mrg };
30 1.1 mrg
31 1.1 mrg /* Return the number of base expressions in "u".
32 1.1 mrg */
33 1.1 mrg isl_size FN(FN(UNION,n),BASE)(__isl_keep UNION *u)
34 1.1 mrg {
35 1.1 mrg return u ? u->table.n : isl_size_error;
36 1.1 mrg }
37 1.1 mrg
38 1.1 mrg S(UNION,foreach_data)
39 1.1 mrg {
40 1.1 mrg isl_stat (*fn)(__isl_take PART *part, void *user);
41 1.1 mrg void *user;
42 1.1 mrg };
43 1.1 mrg
44 1.1 mrg static isl_stat FN(UNION,call_on_copy)(void **entry, void *user)
45 1.1 mrg {
46 1.1 mrg PART *part = *entry;
47 1.1 mrg S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
48 1.1 mrg
49 1.1 mrg part = FN(PART,copy)(part);
50 1.1 mrg if (!part)
51 1.1 mrg return isl_stat_error;
52 1.1 mrg return data->fn(part, data->user);
53 1.1 mrg }
54 1.1 mrg
55 1.1 mrg isl_stat FN(FN(UNION,foreach),BASE)(__isl_keep UNION *u,
56 1.1 mrg isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
57 1.1 mrg {
58 1.1 mrg S(UNION,foreach_data) data = { fn, user };
59 1.1 mrg
60 1.1 mrg if (!u)
61 1.1 mrg return isl_stat_error;
62 1.1 mrg
63 1.1 mrg return isl_hash_table_foreach(u->space->ctx, &u->table,
64 1.1 mrg &FN(UNION,call_on_copy), &data);
65 1.1 mrg }
66 1.1 mrg
67 1.1 mrg /* Is the domain space of "entry" equal to the domain of "space",
68 1.1 mrg * ignoring parameters?
69 1.1 mrg */
70 1.1 mrg static isl_bool FN(UNION,has_same_domain_space_tuples)(const void *entry,
71 1.1 mrg const void *val)
72 1.1 mrg {
73 1.1 mrg PART *part = (PART *)entry;
74 1.1 mrg isl_space *space = (isl_space *) val;
75 1.1 mrg
76 1.1 mrg if (isl_space_is_set(space))
77 1.1 mrg return isl_space_is_set(part->dim);
78 1.1 mrg
79 1.1 mrg return isl_space_tuple_is_equal(part->dim, isl_dim_in,
80 1.1 mrg space, isl_dim_in);
81 1.1 mrg }
82 1.1 mrg
83 1.1 mrg /* Return the entry, if any, in "u" that lives in "space".
84 1.1 mrg * If "reserve" is set, then an entry is created if it does not exist yet.
85 1.1 mrg * Return NULL on error and isl_hash_table_entry_none if no entry was found.
86 1.1 mrg * Note that when "reserve" is set, the function will never return
87 1.1 mrg * isl_hash_table_entry_none.
88 1.1 mrg *
89 1.1 mrg * First look for the entry (if any) with the same domain space.
90 1.1 mrg * If it exists, then check if the range space also matches.
91 1.1 mrg */
92 1.1 mrg static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
93 1.1 mrg __isl_keep UNION *u, __isl_keep isl_space *space, int reserve)
94 1.1 mrg {
95 1.1 mrg isl_ctx *ctx;
96 1.1 mrg uint32_t hash;
97 1.1 mrg struct isl_hash_table_entry *entry;
98 1.1 mrg isl_bool equal;
99 1.1 mrg PART *part;
100 1.1 mrg
101 1.1 mrg if (!u || !space)
102 1.1 mrg return NULL;
103 1.1 mrg
104 1.1 mrg ctx = FN(UNION,get_ctx)(u);
105 1.1 mrg hash = isl_space_get_tuple_domain_hash(space);
106 1.1 mrg entry = isl_hash_table_find(ctx, &u->table, hash,
107 1.1 mrg &FN(UNION,has_same_domain_space_tuples), space, reserve);
108 1.1 mrg if (!entry || entry == isl_hash_table_entry_none)
109 1.1 mrg return entry;
110 1.1 mrg if (reserve && !entry->data)
111 1.1 mrg return entry;
112 1.1 mrg part = entry->data;
113 1.1 mrg equal = isl_space_tuple_is_equal(part->dim, isl_dim_out,
114 1.1 mrg space, isl_dim_out);
115 1.1 mrg if (equal < 0)
116 1.1 mrg return NULL;
117 1.1 mrg if (equal)
118 1.1 mrg return entry;
119 1.1 mrg if (!reserve)
120 1.1 mrg return isl_hash_table_entry_none;
121 1.1 mrg isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
122 1.1 mrg "union expression can only contain a single "
123 1.1 mrg "expression over a given domain", return NULL);
124 1.1 mrg }
125 1.1 mrg
126 1.1 mrg /* Remove "part_entry" from the hash table of "u".
127 1.1 mrg */
128 1.1 mrg static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
129 1.1 mrg struct isl_hash_table_entry *part_entry)
130 1.1 mrg {
131 1.1 mrg isl_ctx *ctx;
132 1.1 mrg
133 1.1 mrg if (!u || !part_entry)
134 1.1 mrg return FN(UNION,free)(u);
135 1.1 mrg
136 1.1 mrg FN(PART,free)(part_entry->data);
137 1.1 mrg ctx = FN(UNION,get_ctx)(u);
138 1.1 mrg isl_hash_table_remove(ctx, &u->table, part_entry);
139 1.1 mrg
140 1.1 mrg return u;
141 1.1 mrg }
142 1.1 mrg
143 1.1 mrg /* Check that the domain of "part" is disjoint from the domain of the entries
144 1.1 mrg * in "u" that are defined on the same domain space, but have a different
145 1.1 mrg * target space.
146 1.1 mrg * Since a UNION with a single entry per domain space is not allowed
147 1.1 mrg * to contain two entries with the same domain space, there cannot be
148 1.1 mrg * any such other entry.
149 1.1 mrg */
150 1.1 mrg static isl_stat FN(UNION,check_disjoint_domain_other)(__isl_keep UNION *u,
151 1.1 mrg __isl_keep PART *part)
152 1.1 mrg {
153 1.1 mrg return isl_stat_ok;
154 1.1 mrg }
155 1.1 mrg
156 1.1 mrg /* Check that the domain of "part1" is disjoint from the domain of "part2".
157 1.1 mrg * This check is performed before "part2" is added to a UNION to ensure
158 1.1 mrg * that the UNION expression remains a function.
159 1.1 mrg * Since a UNION with a single entry per domain space is not allowed
160 1.1 mrg * to contain two entries with the same domain space, fail unconditionally.
161 1.1 mrg */
162 1.1 mrg static isl_stat FN(UNION,check_disjoint_domain)(__isl_keep PART *part1,
163 1.1 mrg __isl_keep PART *part2)
164 1.1 mrg {
165 1.1 mrg isl_die(FN(PART,get_ctx)(part1), isl_error_invalid,
166 1.1 mrg "additional part should live on separate space",
167 1.1 mrg return isl_stat_error);
168 1.1 mrg }
169 1.1 mrg
170 1.1 mrg /* Call "fn" on each part entry of "u".
171 1.1 mrg */
172 1.1 mrg static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
173 1.1 mrg isl_stat (*fn)(void **part, void *user), void *user)
174 1.1 mrg {
175 1.1 mrg isl_ctx *ctx;
176 1.1 mrg
177 1.1 mrg if (!u)
178 1.1 mrg return isl_stat_error;
179 1.1 mrg ctx = FN(UNION,get_ctx)(u);
180 1.1 mrg return isl_hash_table_foreach(ctx, &u->table, fn, user);
181 1.1 mrg }
182 1.1 mrg
183 1.1 mrg static isl_bool FN(PART,has_domain_space_tuples)(__isl_keep PART *part,
184 1.1 mrg __isl_keep isl_space *space);
185 1.1 mrg
186 1.1 mrg /* Do the tuples of "space" correspond to those of the domain of "part"?
187 1.1 mrg * That is, is the domain space of "part" equal to "space", ignoring parameters?
188 1.1 mrg */
189 1.1 mrg static isl_bool FN(UNION,has_domain_space_tuples)(const void *entry,
190 1.1 mrg const void *val)
191 1.1 mrg {
192 1.1 mrg PART *part = (PART *)entry;
193 1.1 mrg isl_space *space = (isl_space *) val;
194 1.1 mrg
195 1.1 mrg return FN(PART,has_domain_space_tuples)(part, space);
196 1.1 mrg }
197 1.1 mrg
198 1.1 mrg /* Call "fn" on each part of "u" that has domain space "space".
199 1.1 mrg *
200 1.1 mrg * Since each entry is defined over a different domain space,
201 1.1 mrg * simply look for an entry with the given domain space and
202 1.1 mrg * call "fn" on the corresponding part if there is one.
203 1.1 mrg */
204 1.1 mrg isl_stat FN(UNION,foreach_on_domain)(__isl_keep UNION *u,
205 1.1 mrg __isl_keep isl_space *space,
206 1.1 mrg isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
207 1.1 mrg {
208 1.1 mrg uint32_t hash;
209 1.1 mrg struct isl_hash_table_entry *entry;
210 1.1 mrg
211 1.1 mrg if (!u || !space)
212 1.1 mrg return isl_stat_error;
213 1.1 mrg hash = isl_space_get_tuple_hash(space);
214 1.1 mrg entry = isl_hash_table_find(FN(UNION,get_ctx)(u), &u->table,
215 1.1 mrg hash, &FN(UNION,has_domain_space_tuples),
216 1.1 mrg space, 0);
217 1.1 mrg if (!entry)
218 1.1 mrg return isl_stat_error;
219 1.1 mrg if (entry == isl_hash_table_entry_none)
220 1.1 mrg return isl_stat_ok;
221 1.1 mrg return fn(FN(PART,copy)(entry->data), user);
222 1.1 mrg }
223 1.1 mrg
224 1.1 mrg static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
225 1.1 mrg {
226 1.1 mrg PART *part = *entry;
227 1.1 mrg FN(PART,free)(part);
228 1.1 mrg return isl_stat_ok;
229 1.1 mrg }
230 1.1 mrg
231 1.1 mrg #include <isl_union_templ.c>
232