2 * Copyright 2010 INRIA Saclay
3 * Copyright 2013 Ecole Normale Superieure
4 * Copyright 2015 INRIA Paris-Rocquencourt
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
9 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
12 * and INRIA Paris-Rocquencourt, Domaine de Voluceau, Rocquenqourt, B.P. 105,
13 * 78153 Le Chesnay Cedex France
16 #include <isl_hash_private.h>
17 #include <isl_union_macro.h>
19 /* A group of expressions defined over the same domain space "domain_space".
20 * The entries of "part_table" are the individual expressions,
21 * keyed on the entire space of the expression.
23 * Each UNION has its own groups, so there can only ever be a single
24 * reference to each group.
27 isl_space
*domain_space
;
28 struct isl_hash_table part_table
;
31 /* A union of expressions defined over different disjoint domains.
32 * "space" describes the parameters.
33 * The entries of "table" are keyed on the domain space of the entry and
34 * contain groups of expressions that are defined over the same domain space.
40 struct isl_hash_table table
;
43 /* Internal data structure for isl_union_*_foreach_group.
44 * "fn" is the function that needs to be called on each group.
46 S(UNION
,foreach_group_data
)
48 isl_stat (*fn
)(__isl_keep
S(UNION
,group
) *group
, void *user
);
52 /* Call data->fn on the group stored at *entry.
54 static isl_stat
FN(UNION
,call_on_group
)(void **entry
, void *user
)
56 S(UNION
,group
) *group
= *entry
;
57 S(UNION
,foreach_group_data
) *data
;
59 data
= (S(UNION
,foreach_group_data
) *) user
;
60 return data
->fn(group
, data
->user
);
63 /* Call "fn" on each group of expressions in "u".
65 static isl_stat
FN(UNION
,foreach_group
)(__isl_keep UNION
*u
,
66 isl_stat (*fn
)(__isl_keep
S(UNION
,group
) *group
, void *user
),
69 S(UNION
,foreach_group_data
) data
= { fn
, user
};
72 return isl_stat_error
;
74 return isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
75 &FN(UNION
,call_on_group
), &data
);
78 /* A isl_union_*_foreach_group callback for counting the total number
79 * of expressions in a UNION. Add the number of expressions in "group"
82 static isl_stat
FN(UNION
,count_part
)(__isl_keep
S(UNION
,group
) *group
,
88 return isl_stat_error
;
90 *n
+= group
->part_table
.n
;
94 /* Return the number of base expressions in "u".
96 int FN(FN(UNION
,n
),BASE
)(__isl_keep UNION
*u
)
101 if (FN(UNION
,foreach_group
)(u
, &FN(UNION
,count_part
), &n
) < 0)
106 /* Free an entry in a group of expressions.
107 * Each entry in such a group is a single expression.
109 static isl_stat
FN(UNION
,free_group_entry
)(void **entry
, void *user
)
117 /* Free all memory allocated for "group" and return NULL.
119 static __isl_null
S(UNION
,group
) *FN(UNION
,group_free
)(
120 __isl_take
S(UNION
,group
) *group
)
127 ctx
= isl_space_get_ctx(group
->domain_space
);
128 isl_hash_table_foreach(ctx
, &group
->part_table
,
129 &FN(UNION
,free_group_entry
), NULL
);
130 isl_hash_table_clear(&group
->part_table
);
131 isl_space_free(group
->domain_space
);
136 /* Allocate a group of expressions defined over the same domain space
137 * with domain space "domain_space" and initial size "size".
139 static __isl_give
S(UNION
,group
) *FN(UNION
,group_alloc
)(
140 __isl_take isl_space
*domain_space
, int size
)
143 S(UNION
,group
) *group
;
147 ctx
= isl_space_get_ctx(domain_space
);
148 group
= isl_calloc_type(ctx
, S(UNION
,group
));
151 group
->domain_space
= domain_space
;
152 if (isl_hash_table_init(ctx
, &group
->part_table
, size
) < 0)
153 return FN(UNION
,group_free
)(group
);
157 isl_space_free(domain_space
);
161 /* Is the space of "entry" equal to "space"?
163 static int FN(UNION
,has_space
)(const void *entry
, const void *val
)
165 PART
*part
= (PART
*) entry
;
166 isl_space
*space
= (isl_space
*) val
;
168 return isl_space_is_equal(part
->dim
, space
);
171 /* Return a group equal to "group", but with a single reference.
172 * Since all groups have only a single reference, simply return "group".
174 static __isl_give
S(UNION
,group
) *FN(UNION
,group_cow
)(
175 __isl_take
S(UNION
,group
) *group
)
180 S(UNION
,foreach_data
)
182 isl_stat (*fn
)(__isl_take PART
*part
, void *user
);
186 static isl_stat
FN(UNION
,call_on_copy
)(void **entry
, void *user
)
189 S(UNION
,foreach_data
) *data
= (S(UNION
,foreach_data
) *) user
;
191 part
= FN(PART
,copy
)(part
);
193 return isl_stat_error
;
194 return data
->fn(part
, data
->user
);
197 /* Call data->fn on a copy of each expression in "group".
199 static isl_stat
FN(UNION
,group_call_on_copy
)(__isl_keep
S(UNION
,group
) *group
,
205 return isl_stat_error
;
207 ctx
= isl_space_get_ctx(group
->domain_space
);
208 return isl_hash_table_foreach(ctx
, &group
->part_table
,
209 &FN(UNION
,call_on_copy
), user
);
212 isl_stat
FN(FN(UNION
,foreach
),BASE
)(__isl_keep UNION
*u
,
213 isl_stat (*fn
)(__isl_take PART
*part
, void *user
), void *user
)
215 S(UNION
,foreach_data
) data
= { fn
, user
};
218 return isl_stat_error
;
220 return FN(UNION
,foreach_group
)(u
, &FN(UNION
,group_call_on_copy
), &data
);
223 /* Is the domain space of the group of expressions at "entry"
226 static int FN(UNION
,group_has_domain_space
)(const void *entry
, const void *val
)
228 S(UNION
,group
) *group
= (S(UNION
,group
) *) entry
;
229 isl_space
*space
= (isl_space
*) val
;
231 return isl_space_is_domain_internal(group
->domain_space
, space
);
234 /* Return the entry, if any, in "u" that lives in "space".
235 * If "reserve" is set, then an entry is created if it does not exist yet.
236 * Return NULL on error and isl_hash_table_entry_none if no entry was found.
237 * Note that when "reserve" is set, the function will never return
238 * isl_hash_table_entry_none.
240 * First look for the group of expressions with the same domain space,
241 * creating one if needed.
242 * Then look for the expression living in the specified space in that group.
244 static struct isl_hash_table_entry
*FN(UNION
,find_part_entry
)(
245 __isl_keep UNION
*u
, __isl_keep isl_space
*space
, int reserve
)
249 struct isl_hash_table_entry
*group_entry
, *part_entry
;
250 S(UNION
,group
) *group
;
255 ctx
= FN(UNION
,get_ctx
)(u
);
256 hash
= isl_space_get_domain_hash(space
);
257 group_entry
= isl_hash_table_find(ctx
, &u
->table
, hash
,
258 &FN(UNION
,group_has_domain_space
), space
, reserve
);
260 return reserve
? NULL
: isl_hash_table_entry_none
;
261 if (reserve
&& !group_entry
->data
) {
262 isl_space
*domain
= isl_space_domain(isl_space_copy(space
));
263 group
= FN(UNION
,group_alloc
)(domain
, 1);
264 group_entry
->data
= group
;
266 group
= group_entry
->data
;
268 group
= FN(UNION
,group_cow
)(group
);
272 hash
= isl_space_get_hash(space
);
273 part_entry
= isl_hash_table_find(ctx
, &group
->part_table
, hash
,
274 &FN(UNION
,has_space
), space
, reserve
);
275 if (!reserve
&& !part_entry
)
276 return isl_hash_table_entry_none
;
280 /* Remove "part_entry" from the hash table of "u".
282 * First look the group_entry in "u" holding the group that
283 * contains "part_entry". Remove "part_entry" from that group.
284 * If the group becomes empty, then also remove the group_entry from "u".
286 static __isl_give UNION
*FN(UNION
,remove_part_entry
)(__isl_take UNION
*u
,
287 struct isl_hash_table_entry
*part_entry
)
292 struct isl_hash_table_entry
*group_entry
;
293 S(UNION
,group
) *group
;
295 if (!u
|| !part_entry
)
296 return FN(UNION
,free
)(u
);
298 part
= part_entry
->data
;
299 ctx
= FN(UNION
,get_ctx
)(u
);
300 hash
= isl_space_get_domain_hash(part
->dim
);
301 group_entry
= isl_hash_table_find(ctx
, &u
->table
, hash
,
302 &FN(UNION
,group_has_domain_space
), part
->dim
, 0);
304 isl_die(ctx
, isl_error_internal
, "missing group",
305 return FN(UNION
,free
)(u
));
306 group
= group_entry
->data
;
307 isl_hash_table_remove(ctx
, &group
->part_table
, part_entry
);
310 if (group
->part_table
.n
!= 0)
313 isl_hash_table_remove(ctx
, &u
->table
, group_entry
);
314 FN(UNION
,group_free
)(group
);
319 /* Are the domains of "part1" and "part2" disjoint?
321 static isl_bool
FN(UNION
,disjoint_domain
)(__isl_keep PART
*part1
,
322 __isl_keep PART
*part2
)
324 isl_set
*dom1
, *dom2
;
327 if (!part1
|| !part2
)
328 return isl_bool_error
;
329 dom1
= FN(PART
,domain
)(FN(PART
,copy
)(part1
));
330 dom2
= FN(PART
,domain
)(FN(PART
,copy
)(part2
));
331 disjoint
= isl_set_is_disjoint(dom1
, dom2
);
338 /* Check that the expression at *entry has a domain that is disjoint
339 * from that of "part", unless they also have the same target space.
341 static isl_stat
FN(UNION
,check_disjoint_domain_entry
)(void **entry
, void *user
)
344 PART
*other
= *entry
;
348 equal
= isl_space_is_equal(part
->dim
, other
->dim
);
350 return isl_stat_error
;
354 disjoint
= FN(UNION
,disjoint_domain
)(part
, other
);
356 return isl_stat_error
;
358 isl_die(FN(PART
,get_ctx
)(part
), isl_error_invalid
,
359 "overlapping domain with other part",
360 return isl_stat_error
);
364 /* Check that the domain of "part" is disjoint from the domain of the entries
365 * in "u" that are defined on the same domain space, but have a different
367 * If there is no group of expressions in "u" with the same domain space,
368 * then everything is fine. Otherwise, check the individual expressions
371 static isl_stat
FN(UNION
,check_disjoint_domain_other
)(__isl_keep UNION
*u
,
372 __isl_keep PART
*part
)
376 struct isl_hash_table_entry
*group_entry
;
377 S(UNION
,group
) *group
;
380 return isl_stat_error
;
381 ctx
= FN(UNION
,get_ctx
)(u
);
382 hash
= isl_space_get_domain_hash(part
->dim
);
383 group_entry
= isl_hash_table_find(ctx
, &u
->table
, hash
,
384 &FN(UNION
,group_has_domain_space
), part
->dim
, 0);
387 group
= group_entry
->data
;
388 return isl_hash_table_foreach(ctx
, &group
->part_table
,
389 &FN(UNION
,check_disjoint_domain_entry
), part
);
392 /* Check that the domain of "part1" is disjoint from the domain of "part2".
393 * This check is performed before "part2" is added to a UNION to ensure
394 * that the UNION expression remains a function.
396 static isl_stat
FN(UNION
,check_disjoint_domain
)(__isl_keep PART
*part1
,
397 __isl_keep PART
*part2
)
401 disjoint
= FN(UNION
,disjoint_domain
)(part1
, part2
);
403 return isl_stat_error
;
405 isl_die(FN(PART
,get_ctx
)(part1
), isl_error_invalid
,
406 "domain of additional part should be disjoint",
407 return isl_stat_error
);
411 /* Internal data structure for isl_union_*_foreach_inplace.
412 * "fn" is the function that needs to be called on each entry.
414 S(UNION
,foreach_inplace_data
)
416 isl_stat (*fn
)(void **entry
, void *user
);
420 /* isl_union_*_foreach_group callback for calling data->fn on
421 * each part entry in the group.
423 static isl_stat
FN(UNION
,group_call_inplace
)(__isl_keep
S(UNION
,group
) *group
,
427 S(UNION
,foreach_inplace_data
) *data
;
430 return isl_stat_error
;
432 data
= (S(UNION
,foreach_inplace_data
) *) user
;
433 ctx
= isl_space_get_ctx(group
->domain_space
);
434 return isl_hash_table_foreach(ctx
, &group
->part_table
,
435 data
->fn
, data
->user
);
438 /* Call "fn" on each part entry of "u".
440 static isl_stat
FN(UNION
,foreach_inplace
)(__isl_keep UNION
*u
,
441 isl_stat (*fn
)(void **part
, void *user
), void *user
)
443 S(UNION
,foreach_inplace_data
) data
= { fn
, user
};
445 return FN(UNION
,foreach_group
)(u
, &FN(UNION
,group_call_inplace
), &data
);
448 /* Does "u" have a single reference?
449 * That is, can we change "u" inplace?
451 static isl_bool
FN(UNION
,has_single_reference
)(__isl_keep UNION
*u
)
454 return isl_bool_error
;
458 static isl_stat
FN(UNION
,free_u_entry
)(void **entry
, void *user
)
460 S(UNION
,group
) *group
= *entry
;
461 FN(UNION
,group_free
)(group
);
465 #include <isl_union_templ.c>