1 /*
2  * Copyright 2018      Cerebras Systems
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege,
7  * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
8  */
9 
10 #include <isl/space.h>
11 
12 /* Merge parameter "param" into the input dimension "i" of "obj".
13  *
14  * First plug in the parameter for the input dimension in "obj".
15  * The drop the (now defunct) input dimension and
16  * move the parameter in its original position.
17  * Since dimension manipulations destroy spaces, modify the space
18  * separately by only dropping the parameter.
19  */
FN(TYPE,merge_param)20 static __isl_give TYPE *FN(TYPE,merge_param)(__isl_take TYPE *obj, int i,
21 	int param)
22 {
23 	isl_id *id;
24 	isl_aff *aff;
25 	isl_space *space;
26 	isl_multi_aff *ma;
27 
28 	space = FN(TYPE,get_domain_space)(obj);
29 	id = isl_space_get_dim_id(space, isl_dim_param, param);
30 	aff = isl_aff_param_on_domain_space_id(isl_space_copy(space), id);
31 	space = isl_space_map_from_set(space);
32 	ma = isl_multi_aff_identity(space);
33 	ma = isl_multi_aff_set_aff(ma, i, aff);
34 	obj = FN(TYPE,pullback_multi_aff)(obj, ma);
35 	space = FN(TYPE,get_domain_space)(obj);
36 	obj = FN(TYPE,drop_dims)(obj, isl_dim_in, i, 1);
37 	obj = FN(TYPE,move_dims)(obj, isl_dim_in, i, isl_dim_param, param, 1);
38 	space = isl_space_drop_dims(space, isl_dim_param, param, 1);
39 	obj = FN(TYPE,reset_domain_space)(obj, space);
40 
41 	return obj;
42 }
43 
44 /* Given a tuple of identifiers "tuple" that correspond
45  * to the initial input dimensions of "obj",
46  * if any of those identifiers appear as parameters
47  * in "obj", then equate those parameters with the corresponding
48  * input dimensions and project out the parameters.
49  * The result therefore has no such parameters.
50  */
FN(TYPE,equate_initial_params)51 static __isl_give TYPE *FN(TYPE,equate_initial_params)(__isl_take TYPE *obj,
52 	__isl_keep isl_multi_id *tuple)
53 {
54 	int i;
55 	isl_size n;
56 
57 	n = isl_multi_id_size(tuple);
58 	if (n < 0)
59 		return FN(TYPE,free)(obj);
60 	for (i = 0; i < n; ++i) {
61 		isl_id *id;
62 		int pos;
63 
64 		id = isl_multi_id_get_at(tuple, i);
65 		if (!id)
66 			return FN(TYPE,free)(obj);
67 		pos = FN(TYPE,find_dim_by_id)(obj, isl_dim_param, id);
68 		isl_id_free(id);
69 		if (pos < 0)
70 			continue;
71 		obj = FN(TYPE,merge_param)(obj, i, pos);
72 	}
73 
74 	return obj;
75 }
76 
77 /* Given a tuple of identifiers "tuple" in a space that corresponds
78  * to the domain of "obj", if any of those identifiers appear as parameters
79  * in "obj", then equate those parameters with the corresponding
80  * input dimensions and project out the parameters.
81  * The result therefore has no such parameters.
82  */
FN(TYPE,equate_domain_params)83 static __isl_give TYPE *FN(TYPE,equate_domain_params)(__isl_take TYPE *obj,
84 	__isl_keep isl_multi_id *tuple)
85 {
86 	isl_stat r;
87 	isl_space *obj_space, *tuple_space;
88 
89 	obj_space = FN(TYPE,get_space)(obj);
90 	tuple_space = isl_multi_id_peek_space(tuple);
91 	r = isl_space_check_domain_tuples(tuple_space, obj_space);
92 	isl_space_free(obj_space);
93 	if (r < 0)
94 		return FN(TYPE,free)(obj);
95 
96 	return FN(TYPE,equate_initial_params)(obj, tuple);
97 }
98 
99 /* Bind the domain dimensions of the function "obj" to parameters
100  * with identifiers specified by "tuple", living in the same space
101  * as the domain of "obj".
102  *
103  * If no parameters with these identifiers appear in "obj" already,
104  * then the domain dimensions are simply reinterpreted as parameters.
105  * Otherwise, the parameters are first equated to the corresponding
106  * domain dimensions.
107  */
FN(TYPE,bind_domain)108 __isl_give TYPE *FN(TYPE,bind_domain)(__isl_take TYPE *obj,
109 	__isl_take isl_multi_id *tuple)
110 {
111 	isl_space *space;
112 
113 	obj = FN(TYPE,equate_domain_params)(obj, tuple);
114 	space = FN(TYPE,get_space)(obj);
115 	space = isl_space_bind_map_domain(space, tuple);
116 	isl_multi_id_free(tuple);
117 	obj = FN(TYPE,reset_space)(obj, space);
118 
119 	return obj;
120 }
121 
122 /* Given a tuple of identifiers "tuple" in a space that corresponds
123  * to the domain of the wrapped relation in the domain of "obj",
124  * if any of those identifiers appear as parameters
125  * in "obj", then equate those parameters with the corresponding
126  * input dimensions and project out the parameters.
127  * The result therefore has no such parameters.
128  */
FN(TYPE,equate_domain_wrapped_domain_params)129 static __isl_give TYPE *FN(TYPE,equate_domain_wrapped_domain_params)(
130 	__isl_take TYPE *obj, __isl_keep isl_multi_id *tuple)
131 {
132 	isl_stat r;
133 	isl_space *obj_space, *tuple_space;
134 
135 	obj_space = FN(TYPE,get_space)(obj);
136 	tuple_space = isl_multi_id_peek_space(tuple);
137 	r = isl_space_check_domain_wrapped_domain_tuples(tuple_space,
138 							obj_space);
139 	isl_space_free(obj_space);
140 	if (r < 0)
141 		return FN(TYPE,free)(obj);
142 
143 	return FN(TYPE,equate_initial_params)(obj, tuple);
144 }
145 
146 /* Given a function living in a space of the form [A -> B] -> C and
147  * a tuple of identifiers in A, bind the domain dimensions of the relation
148  * wrapped in the domain of "obj" with identifiers specified by "tuple",
149  * returning a function in the space B -> C.
150  *
151  * If no parameters with these identifiers appear in "obj" already,
152  * then the domain dimensions are simply reinterpreted as parameters.
153  * Otherwise, the parameters are first equated to the corresponding
154  * domain dimensions.
155  */
FN(TYPE,bind_domain_wrapped_domain)156 __isl_give TYPE *FN(TYPE,bind_domain_wrapped_domain)(__isl_take TYPE *obj,
157 	__isl_take isl_multi_id *tuple)
158 {
159 	isl_space *space;
160 
161 	obj = FN(TYPE,equate_domain_wrapped_domain_params)(obj, tuple);
162 	space = FN(TYPE,get_space)(obj);
163 	space = isl_space_bind_domain_wrapped_domain(space, tuple);
164 	isl_multi_id_free(tuple);
165 	obj = FN(TYPE,reset_space)(obj, space);
166 
167 	return obj;
168 }
169