1 | #ifndef ISL_AST_BUILD_PRIVATE_H |
2 | #define ISL_AST_BUILD_PRIVATE_H |
3 | |
4 | #include <isl/aff.h> |
5 | #include <isl/ast.h> |
6 | #include <isl/ast_build.h> |
7 | #include <isl/set.h> |
8 | #include <isl/list.h> |
9 | #include <isl/schedule_node.h> |
10 | |
11 | /* An isl_ast_build represents the context in which AST is being |
12 | * generated. That is, it (mostly) contains information about outer |
13 | * loops that can be used to simplify inner loops. |
14 | * |
15 | * "domain" represents constraints on the internal schedule domain, |
16 | * corresponding to the context of the AST generation and the constraints |
17 | * implied by the loops that have already been generated. |
18 | * When an isl_ast_build is first created, outside any AST generation, |
19 | * the domain is typically a parameter set. It is only when a AST |
20 | * generation phase is initiated that the domain of the isl_ast_build |
21 | * is changed to refer to the internal schedule domain. |
22 | * The domain then lives in a space of the form |
23 | * |
24 | * S |
25 | * |
26 | * or |
27 | * |
28 | * [O -> S] |
29 | * |
30 | * O represents the loops generated in outer AST generations. |
31 | * S represents the loops (both generated and to be generated) |
32 | * of the current AST generation. |
33 | * Both include eliminated loops. |
34 | * "domain" is expected not to have any unknown divs because |
35 | * it is used as the context argument in a call to isl_basic_set_gist |
36 | * in isl_ast_build_compute_gist_basic_set. |
37 | * |
38 | * "depth" is equal to the number of loops that have already |
39 | * been generated (including those in outer AST generations). |
40 | * "outer_pos" is equal to the number of loops in outer AST generations. |
41 | * |
42 | * "generated" is a superset of "domain" corresponding to those |
43 | * constraints that were either given by the user or that have |
44 | * effectively been generated (as bounds on a for loop). |
45 | * |
46 | * "pending" is a superset of "domain" corresponding to the constraints |
47 | * that still need to be generated (as guards), but that may end up |
48 | * not getting generated if they are implied by any constraints |
49 | * enforced by inner loops. |
50 | * |
51 | * "strides" contains the stride of each loop. The number of elements |
52 | * is equal to the number of dimensions in "domain". |
53 | * "offsets" contains the offsets of strided loops. If s is the stride |
54 | * for a given dimension and f is the corresponding offset, then the |
55 | * dimension takes on values |
56 | * |
57 | * f + s a |
58 | * |
59 | * with a an integer. For non-strided loops, the offset is zero. |
60 | * |
61 | * "iterators" contains the loop iterators of both generated and |
62 | * to be generated loops. The number of elements is at least as |
63 | * large as the dimension of the internal schedule domain. The |
64 | * number may be larger, in which case the additional ids can be |
65 | * used in a nested AST generation should the schedule be non-injective. |
66 | * |
67 | * "values" lives in the space |
68 | * |
69 | * [O -> S] -> [O -> S] (or S -> S) |
70 | * |
71 | * and expresses (if possible) loop iterators in terms of parameters |
72 | * and outer loop iterators. If the value of a given loop iterator |
73 | * cannot be expressed as an affine expression (either because the iterator |
74 | * attains multiple values or because the single value is a piecewise |
75 | * affine expression), then it is expressed in "values" as being equal |
76 | * to itself. |
77 | * |
78 | * "value" is the value of the loop iterator at the current depth. |
79 | * It is NULL if it has not been computed yet or if the value of the |
80 | * given loop iterator cannot be expressed as a piecewise affine expression |
81 | * (because the iterator attains multiple values). |
82 | * |
83 | * "schedule_map" maps the internal schedule domain to the external schedule |
84 | * domain. It may be NULL if it hasn't been computed yet. |
85 | * See isl_ast_build_get_schedule_map_multi_aff. |
86 | * |
87 | * "internal2input" maps the internal schedule domain to the original |
88 | * input schedule domain. In case of a schedule tree input, the original |
89 | * input schedule domain consist of the flat product of all outer |
90 | * band node spaces, including the current band node. |
91 | * It may be NULL if there no longer is such a uniform mapping |
92 | * (because different iterations have been rescheduled differently). |
93 | * |
94 | * "options" contains the AST build options in case we are generating |
95 | * an AST from a flat schedule map. When creating an AST from a schedule |
96 | * tree, this field is ignored. |
97 | * |
98 | * The "create_leaf" callback is called for every leaf in the generated AST. |
99 | * The callback is responsible for creating the node to be placed at those |
100 | * leaves. If this callback is not set, then isl will generated user |
101 | * nodes with call expressions corresponding to an element of the domain. |
102 | * |
103 | * The "at_each_domain" callback is called on every node created to represent |
104 | * an element of the domain. Each of these nodes is a user node |
105 | * with as expression a call expression. |
106 | * |
107 | * The "before_each_for" callback is called on each for node before |
108 | * its children have been created. |
109 | * |
110 | * The "after_each_for" callback is called on each for node after |
111 | * its children have been created. |
112 | * |
113 | * The "before_each_mark" callback is called before we handle the subtree |
114 | * of an isl_schedule_node_mark node. |
115 | * |
116 | * The "after_each_mark" callback is called after we have handled the subtree |
117 | * of an isl_schedule_node_mark node. |
118 | * |
119 | * "executed" contains the inverse schedule at this point |
120 | * of the AST generation. |
121 | * It is currently only used in isl_ast_build_get_schedule, which is |
122 | * in turn only used by user code from within a callback. |
123 | * The value is set right before we may be calling such a callback. |
124 | * |
125 | * "single_valued" is set if the current inverse schedule (which may or may |
126 | * not be stored in "executed") is known to be single valued, specifically |
127 | * an inverse schedule that was not (appeared not to be) single valued |
128 | * is extended to a single valued inverse schedule. This is mainly used |
129 | * to avoid an infinite recursion when we fail to detect later on that |
130 | * the extended inverse schedule is single valued. |
131 | * |
132 | * "node" points to the current band node in case we are generating |
133 | * an AST from a schedule tree. It may be NULL if we are not generating |
134 | * an AST from a schedule tree or if we are not inside a band node. |
135 | * |
136 | * "loop_type" originally contains loop AST generation types for |
137 | * the "n" members of "node" and it is updated (along with "n") when |
138 | * a schedule dimension is inserted. |
139 | * It is NULL if "node" is NULL. |
140 | * |
141 | * "isolated" is the piece of the schedule domain isolated by the isolate |
142 | * option on the current band. This set may be NULL if we have not checked |
143 | * for the isolate option yet. |
144 | */ |
145 | struct isl_ast_build { |
146 | int ref; |
147 | |
148 | int outer_pos; |
149 | int depth; |
150 | |
151 | isl_id_list *iterators; |
152 | |
153 | isl_set *domain; |
154 | isl_set *generated; |
155 | isl_set *pending; |
156 | isl_multi_aff *values; |
157 | |
158 | isl_pw_aff *value; |
159 | |
160 | isl_vec *strides; |
161 | isl_multi_aff *offsets; |
162 | |
163 | isl_multi_aff *schedule_map; |
164 | isl_multi_aff *internal2input; |
165 | |
166 | isl_union_map *options; |
167 | |
168 | __isl_give isl_ast_node *(*at_each_domain)( |
169 | __isl_take isl_ast_node *node, |
170 | __isl_keep isl_ast_build *build, void *user); |
171 | void *at_each_domain_user; |
172 | |
173 | __isl_give isl_id *(*before_each_for)( |
174 | __isl_keep isl_ast_build *context, void *user); |
175 | void *before_each_for_user; |
176 | __isl_give isl_ast_node *(*after_each_for)( |
177 | __isl_take isl_ast_node *node, |
178 | __isl_keep isl_ast_build *context, void *user); |
179 | void *after_each_for_user; |
180 | |
181 | isl_stat (*before_each_mark)(__isl_keep isl_id *mark, |
182 | __isl_keep isl_ast_build *build, void *user); |
183 | void *before_each_mark_user; |
184 | __isl_give isl_ast_node *(*after_each_mark)( |
185 | __isl_take isl_ast_node *node, |
186 | __isl_keep isl_ast_build *context, void *user); |
187 | void *after_each_mark_user; |
188 | |
189 | __isl_give isl_ast_node *(*create_leaf)( |
190 | __isl_take isl_ast_build *build, void *user); |
191 | void *create_leaf_user; |
192 | |
193 | isl_union_map *executed; |
194 | int single_valued; |
195 | |
196 | isl_schedule_node *node; |
197 | int n; |
198 | enum isl_ast_loop_type *loop_type; |
199 | isl_set *isolated; |
200 | }; |
201 | |
202 | __isl_give isl_ast_build *isl_ast_build_clear_local_info( |
203 | __isl_take isl_ast_build *build); |
204 | __isl_give isl_ast_build *isl_ast_build_increase_depth( |
205 | __isl_take isl_ast_build *build); |
206 | isl_size isl_ast_build_get_depth(__isl_keep isl_ast_build *build); |
207 | isl_size isl_ast_build_dim(__isl_keep isl_ast_build *build, |
208 | enum isl_dim_type type); |
209 | __isl_give isl_space *isl_ast_build_get_space( |
210 | __isl_keep isl_ast_build *build, int internal); |
211 | __isl_give isl_ast_build *isl_ast_build_align_params( |
212 | __isl_take isl_ast_build *build, __isl_take isl_space *model); |
213 | __isl_give isl_ast_build *isl_ast_build_cow( |
214 | __isl_take isl_ast_build *build); |
215 | __isl_give isl_ast_build *isl_ast_build_insert_dim( |
216 | __isl_take isl_ast_build *build, int pos); |
217 | __isl_give isl_ast_build *isl_ast_build_scale_down( |
218 | __isl_take isl_ast_build *build, __isl_take isl_val *m, |
219 | __isl_take isl_union_map *umap); |
220 | __isl_give isl_ast_build *isl_ast_build_product( |
221 | __isl_take isl_ast_build *build, __isl_take isl_space *embedding); |
222 | __isl_give isl_ast_build *isl_ast_build_set_loop_bounds( |
223 | __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds); |
224 | __isl_give isl_ast_build *isl_ast_build_set_pending_generated( |
225 | __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds); |
226 | __isl_give isl_ast_build *isl_ast_build_detect_strides( |
227 | __isl_take isl_ast_build *build, __isl_take isl_set *set); |
228 | __isl_give isl_ast_build *isl_ast_build_include_stride( |
229 | __isl_take isl_ast_build *build); |
230 | __isl_give isl_ast_build *isl_ast_build_set_executed( |
231 | __isl_take isl_ast_build *build, |
232 | __isl_take isl_union_map *executed); |
233 | __isl_give isl_ast_build *isl_ast_build_set_single_valued( |
234 | __isl_take isl_ast_build *build, int sv); |
235 | __isl_give isl_multi_aff *isl_ast_build_get_internal2input( |
236 | __isl_keep isl_ast_build *build); |
237 | __isl_give isl_set *isl_ast_build_get_domain( |
238 | __isl_keep isl_ast_build *build); |
239 | __isl_give isl_set *isl_ast_build_get_pending( |
240 | __isl_keep isl_ast_build *build); |
241 | __isl_give isl_set *isl_ast_build_get_generated( |
242 | __isl_keep isl_ast_build *build); |
243 | __isl_give isl_ast_build *isl_ast_build_restrict_generated( |
244 | __isl_take isl_ast_build *build, __isl_take isl_set *set); |
245 | __isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard( |
246 | __isl_take isl_ast_build *build, __isl_take isl_set *guard); |
247 | isl_bool isl_ast_build_need_schedule_map(__isl_keep isl_ast_build *build); |
248 | __isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff( |
249 | __isl_keep isl_ast_build *build); |
250 | __isl_give isl_map *isl_ast_build_get_schedule_map( |
251 | __isl_keep isl_ast_build *build); |
252 | isl_bool isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build, |
253 | int pos); |
254 | int isl_ast_build_has_value(__isl_keep isl_ast_build *build); |
255 | __isl_give isl_id *isl_ast_build_get_iterator_id( |
256 | __isl_keep isl_ast_build *build, int pos); |
257 | |
258 | int isl_ast_build_has_schedule_node(__isl_keep isl_ast_build *build); |
259 | __isl_give isl_schedule_node *isl_ast_build_get_schedule_node( |
260 | __isl_keep isl_ast_build *build); |
261 | __isl_give isl_ast_build *isl_ast_build_set_schedule_node( |
262 | __isl_take isl_ast_build *build, |
263 | __isl_take isl_schedule_node *node); |
264 | __isl_give isl_ast_build *isl_ast_build_reset_schedule_node( |
265 | __isl_take isl_ast_build *build); |
266 | |
267 | __isl_give isl_ast_build *( |
268 | __isl_take isl_ast_build *build); |
269 | int isl_ast_build_has_isolated(__isl_keep isl_ast_build *build); |
270 | __isl_give isl_set *isl_ast_build_get_isolated( |
271 | __isl_keep isl_ast_build *build); |
272 | |
273 | __isl_give isl_basic_set *isl_ast_build_specialize_basic_set( |
274 | __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset); |
275 | __isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set( |
276 | __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset); |
277 | __isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build, |
278 | __isl_take isl_set *set); |
279 | __isl_give isl_set *isl_ast_build_compute_gist( |
280 | __isl_keep isl_ast_build *build, __isl_take isl_set *set); |
281 | __isl_give isl_map *isl_ast_build_compute_gist_map_domain( |
282 | __isl_keep isl_ast_build *build, __isl_take isl_map *map); |
283 | __isl_give isl_aff *isl_ast_build_compute_gist_aff( |
284 | __isl_keep isl_ast_build *build, __isl_take isl_aff *aff); |
285 | __isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff( |
286 | __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa); |
287 | __isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff( |
288 | __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma); |
289 | |
290 | __isl_give isl_union_map *isl_ast_build_substitute_values_union_map_domain( |
291 | __isl_keep isl_ast_build *build, __isl_take isl_union_map *umap); |
292 | |
293 | isl_bool isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build, |
294 | __isl_keep isl_aff *aff); |
295 | |
296 | isl_bool isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos); |
297 | __isl_give isl_aff *isl_ast_build_get_offset(__isl_keep isl_ast_build *build, |
298 | int pos); |
299 | __isl_give isl_val *isl_ast_build_get_stride(__isl_keep isl_ast_build *build, |
300 | int pos); |
301 | __isl_give isl_set *isl_ast_build_get_stride_constraint( |
302 | __isl_keep isl_ast_build *build); |
303 | __isl_give isl_multi_aff *isl_ast_build_get_stride_expansion( |
304 | __isl_keep isl_ast_build *build); |
305 | |
306 | void isl_ast_build_dump(__isl_keep isl_ast_build *build); |
307 | |
308 | __isl_give isl_set *isl_ast_build_get_option_domain( |
309 | __isl_keep isl_ast_build *build, enum isl_ast_loop_type type); |
310 | __isl_give isl_map *isl_ast_build_get_separation_class( |
311 | __isl_keep isl_ast_build *build); |
312 | __isl_give isl_set *isl_ast_build_eliminate( |
313 | __isl_keep isl_ast_build *build, __isl_take isl_set *domain); |
314 | __isl_give isl_set *isl_ast_build_eliminate_inner( |
315 | __isl_keep isl_ast_build *build, __isl_take isl_set *set); |
316 | __isl_give isl_set *isl_ast_build_eliminate_divs( |
317 | __isl_keep isl_ast_build *build, __isl_take isl_set *set); |
318 | |
319 | enum isl_ast_loop_type isl_ast_build_get_loop_type( |
320 | __isl_keep isl_ast_build *build, int isolated); |
321 | |
322 | __isl_give isl_map *isl_ast_build_map_to_iterator( |
323 | __isl_keep isl_ast_build *build, __isl_take isl_set *set); |
324 | |
325 | int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build); |
326 | |
327 | #endif |
328 | |