Home | History | Annotate | Line # | Download | only in dist
      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