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
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 isl_size
FN(FN(UNION
,n
),BASE
)(__isl_keep UNION
*u
)
101 if (FN(UNION
,foreach_group
)(u
, &FN(UNION
,count_part
), &n
) < 0)
102 return isl_size_error
;
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 isl_bool
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"
224 * equal to that of "space"?
226 static isl_bool
FN(UNION
,group_has_same_domain_space
)(const void *entry
,
229 S(UNION
,group
) *group
= (S(UNION
,group
) *) entry
;
230 isl_space
*space
= (isl_space
*) val
;
232 return isl_space_is_domain_internal(group
->domain_space
, space
);
235 /* Return the entry, if any, in "u" that lives in "space".
236 * If "reserve" is set, then an entry is created if it does not exist yet.
237 * Return NULL on error and isl_hash_table_entry_none if no entry was found.
238 * Note that when "reserve" is set, the function will never return
239 * isl_hash_table_entry_none.
241 * First look for the group of expressions with the same domain space,
242 * creating one if needed.
243 * Then look for the expression living in the specified space in that group.
245 static struct isl_hash_table_entry
*FN(UNION
,find_part_entry
)(
246 __isl_keep UNION
*u
, __isl_keep isl_space
*space
, int reserve
)
250 struct isl_hash_table_entry
*group_entry
;
251 S(UNION
,group
) *group
;
256 ctx
= FN(UNION
,get_ctx
)(u
);
257 hash
= isl_space_get_domain_hash(space
);
258 group_entry
= isl_hash_table_find(ctx
, &u
->table
, hash
,
259 &FN(UNION
,group_has_same_domain_space
), space
, reserve
);
260 if (!group_entry
|| group_entry
== isl_hash_table_entry_none
)
262 if (reserve
&& !group_entry
->data
) {
263 isl_space
*domain
= isl_space_domain(isl_space_copy(space
));
264 group
= FN(UNION
,group_alloc
)(domain
, 1);
265 group_entry
->data
= group
;
267 group
= group_entry
->data
;
269 group
= FN(UNION
,group_cow
)(group
);
273 hash
= isl_space_get_hash(space
);
274 return isl_hash_table_find(ctx
, &group
->part_table
, hash
,
275 &FN(UNION
,has_space
), space
, reserve
);
278 /* Remove "part_entry" from the hash table of "u".
280 * First look the group_entry in "u" holding the group that
281 * contains "part_entry". Remove "part_entry" from that group.
282 * If the group becomes empty, then also remove the group_entry from "u".
284 static __isl_give UNION
*FN(UNION
,remove_part_entry
)(__isl_take UNION
*u
,
285 struct isl_hash_table_entry
*part_entry
)
291 struct isl_hash_table_entry
*group_entry
;
292 S(UNION
,group
) *group
;
294 if (!u
|| !part_entry
)
295 return FN(UNION
,free
)(u
);
297 part
= part_entry
->data
;
298 ctx
= FN(UNION
,get_ctx
)(u
);
299 space
= FN(PART
,peek_space
)(part
);
300 hash
= isl_space_get_domain_hash(space
);
301 group_entry
= isl_hash_table_find(ctx
, &u
->table
, hash
,
302 &FN(UNION
,group_has_same_domain_space
), space
, 0);
304 return FN(UNION
,free
)(u
);
305 if (group_entry
== isl_hash_table_entry_none
)
306 isl_die(ctx
, isl_error_internal
, "missing group",
307 return FN(UNION
,free
)(u
));
308 group
= group_entry
->data
;
309 isl_hash_table_remove(ctx
, &group
->part_table
, part_entry
);
312 if (group
->part_table
.n
!= 0)
315 isl_hash_table_remove(ctx
, &u
->table
, group_entry
);
316 FN(UNION
,group_free
)(group
);
321 /* Are the domains of "part1" and "part2" disjoint?
323 static isl_bool
FN(UNION
,disjoint_domain
)(__isl_keep PART
*part1
,
324 __isl_keep PART
*part2
)
326 isl_set
*dom1
, *dom2
;
329 if (!part1
|| !part2
)
330 return isl_bool_error
;
331 dom1
= FN(PART
,domain
)(FN(PART
,copy
)(part1
));
332 dom2
= FN(PART
,domain
)(FN(PART
,copy
)(part2
));
333 disjoint
= isl_set_is_disjoint(dom1
, dom2
);
340 /* Check that the expression at *entry has a domain that is disjoint
341 * from that of "part", unless they also have the same target space.
343 static isl_stat
FN(UNION
,check_disjoint_domain_entry
)(void **entry
, void *user
)
346 PART
*other
= *entry
;
350 equal
= isl_space_is_equal(part
->dim
, other
->dim
);
352 return isl_stat_error
;
356 disjoint
= FN(UNION
,disjoint_domain
)(part
, other
);
358 return isl_stat_error
;
360 isl_die(FN(PART
,get_ctx
)(part
), isl_error_invalid
,
361 "overlapping domain with other part",
362 return isl_stat_error
);
366 /* Check that the domain of "part" is disjoint from the domain of the entries
367 * in "u" that are defined on the same domain space, but have a different
369 * If there is no group of expressions in "u" with the same domain space,
370 * then everything is fine. Otherwise, check the individual expressions
373 static isl_stat
FN(UNION
,check_disjoint_domain_other
)(__isl_keep UNION
*u
,
374 __isl_keep PART
*part
)
379 struct isl_hash_table_entry
*group_entry
;
380 S(UNION
,group
) *group
;
383 return isl_stat_error
;
384 ctx
= FN(UNION
,get_ctx
)(u
);
385 space
= FN(PART
,peek_space
)(part
);
386 hash
= isl_space_get_domain_hash(space
);
387 group_entry
= isl_hash_table_find(ctx
, &u
->table
, hash
,
388 &FN(UNION
,group_has_same_domain_space
), space
, 0);
390 return isl_stat_error
;
391 if (group_entry
== isl_hash_table_entry_none
)
393 group
= group_entry
->data
;
394 return isl_hash_table_foreach(ctx
, &group
->part_table
,
395 &FN(UNION
,check_disjoint_domain_entry
), part
);
398 /* Check that the domain of "part1" is disjoint from the domain of "part2".
399 * This check is performed before "part2" is added to a UNION to ensure
400 * that the UNION expression remains a function.
402 static isl_stat
FN(UNION
,check_disjoint_domain
)(__isl_keep PART
*part1
,
403 __isl_keep PART
*part2
)
407 disjoint
= FN(UNION
,disjoint_domain
)(part1
, part2
);
409 return isl_stat_error
;
411 isl_die(FN(PART
,get_ctx
)(part1
), isl_error_invalid
,
412 "domain of additional part should be disjoint",
413 return isl_stat_error
);
417 /* Internal data structure for isl_union_*_foreach_inplace.
418 * "fn" is the function that needs to be called on each entry.
420 S(UNION
,foreach_inplace_data
)
422 isl_stat (*fn
)(void **entry
, void *user
);
426 /* isl_union_*_foreach_group callback for calling data->fn on
427 * each part entry in the group.
429 static isl_stat
FN(UNION
,group_call_inplace
)(__isl_keep
S(UNION
,group
) *group
,
433 S(UNION
,foreach_inplace_data
) *data
;
436 return isl_stat_error
;
438 data
= (S(UNION
,foreach_inplace_data
) *) user
;
439 ctx
= isl_space_get_ctx(group
->domain_space
);
440 return isl_hash_table_foreach(ctx
, &group
->part_table
,
441 data
->fn
, data
->user
);
444 /* Call "fn" on each part entry of "u".
446 static isl_stat
FN(UNION
,foreach_inplace
)(__isl_keep UNION
*u
,
447 isl_stat (*fn
)(void **part
, void *user
), void *user
)
449 S(UNION
,foreach_inplace_data
) data
= { fn
, user
};
451 return FN(UNION
,foreach_group
)(u
, &FN(UNION
,group_call_inplace
), &data
);
454 static isl_stat
FN(UNION
,free_u_entry
)(void **entry
, void *user
)
456 S(UNION
,group
) *group
= *entry
;
457 FN(UNION
,group_free
)(group
);
461 /* Set "single" to true if this group of expressions
462 * contains an expression living in exactly one space.
464 static isl_stat
FN(UNION
,group_single_space
)(__isl_keep
S(UNION
,group
) *group
,
467 isl_bool
*single
= user
;
470 return isl_stat_error
;
471 *single
= isl_bool_ok(group
->part_table
.n
== 1);
475 /* Can this union expression be converted to a single base expression?
476 * That is, does it contain a base expression in exactly one space?
477 * In particular, is only one domain space involved and
478 * is only a single expression associated to that domain?
480 isl_bool
FN(FN(UNION
,isa
),BASE
)(__isl_take UNION
*u
)
485 return isl_bool_error
;
487 return isl_bool_false
;
488 if (FN(UNION
,foreach_group
)(u
,
489 &FN(UNION
,group_single_space
), &single
) < 0)
490 return isl_bool_error
;
494 /* Callback for isl_union_*_foreach_inplace call
495 * on a union expression with a single base expression.
496 * Store that base expression in "user".
497 * This callback should only be called once
498 * for any given isl_union_*_foreach_inplace call.
500 static isl_stat
FN(UNION
,extract_part
)(void **entry
, void *user
)
502 PART
**part_p
= user
;
506 isl_die(FN(PART
,get_ctx
)(part
), isl_error_internal
,
507 "more than one part", return isl_stat_error
);
508 *part_p
= FN(PART
,copy
)(part
);
510 return isl_stat_error
;
514 /* Convert the union expression to its single base expression.
516 __isl_give PART
*FN(FN(UNION
,as
),BASE
)(__isl_take UNION
*u
)
518 isl_bool has_single_space
;
521 has_single_space
= FN(FN(UNION
,isa
),BASE
)(u
);
522 if (has_single_space
< 0)
524 if (!has_single_space
)
525 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
526 "expecting elements in exactly one space",
528 if (FN(UNION
,foreach_inplace
)(u
, &FN(UNION
,extract_part
), &part
) < 0)
529 part
= FN(PART
,free
)(part
);
537 #include <isl_union_templ.c>