pet_codegen.c: add missing include
[pet.git] / summary.c
blob9173b744bd72a3da021b914a6240ea846b9438d8
1 /*
2 * Copyright 2014 Ecole Normale Superieure. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY ECOLE NORMALE SUPERIEURE ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECOLE NORMALE SUPERIEURE OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Ecole Normale Superieure.
34 #include <isl/space.h>
35 #include <isl/union_set.h>
37 #include "aff.h"
38 #include "summary.h"
40 /* A pet_function_summary objects represents an argument of a function.
42 * If "type" is pet_arg_int, then the argument has an integer type and
43 * can be used to describe the accesses performed by the pet_arg_array
44 * arguments. In this case, "id" refers to the formal argument.
46 * If "type" is pet_arg_array, then we keep track of the accesses
47 * through this argument in the access relations in "access".
48 * The domains of these access relations refer to the integer arguments
49 * of the function. That is, the input dimensions correspond
50 * to the arguments of type pet_arg_int.
52 * If "type" is pet_arg_other, then we do not keep track of any
53 * further information.
55 struct pet_function_summary_arg {
56 enum pet_arg_type type;
58 union {
59 isl_id *id;
60 isl_union_map *access[pet_expr_access_end];
64 /* A pet_function_summary object keeps track of the accesses performed
65 * by a function in terms of the function arguments.
67 * "n" is the number of arguments.
68 * "arg" contains a description of the "n" arguments.
70 struct pet_function_summary {
71 int ref;
72 isl_ctx *ctx;
74 unsigned n;
76 struct pet_function_summary_arg arg[];
79 /* Construct and return a new pet_function_summary object with
80 * "n_arg" arguments, initialized to pet_arg_other.
82 __isl_give pet_function_summary *pet_function_summary_alloc(isl_ctx *ctx,
83 unsigned n_arg)
85 pet_function_summary *summary;
86 int i;
88 summary = isl_calloc(ctx, struct pet_function_summary,
89 sizeof(struct pet_function_summary) +
90 n_arg * sizeof(struct pet_function_summary_arg));
91 if (!summary)
92 return summary;
94 summary->ctx = ctx;
95 isl_ctx_ref(ctx);
96 summary->ref = 1;
97 summary->n = n_arg;
98 for (i = 0; i < n_arg; ++i)
99 summary->arg[i].type = pet_arg_other;
101 return summary;
104 /* Return an extra reference to "summary".
106 __isl_give pet_function_summary *pet_function_summary_copy(
107 __isl_keep pet_function_summary *summary)
109 if (!summary)
110 return NULL;
112 summary->ref++;
113 return summary;
116 /* Return the isl_ctx in which "summary" was created.
118 isl_ctx *pet_function_summary_get_ctx(__isl_keep pet_function_summary *summary)
120 return summary ? summary->ctx : NULL;
123 /* Free the data stored in "arg".
125 static void free_arg(struct pet_function_summary_arg *arg)
127 enum pet_expr_access_type type;
129 if (arg->type == pet_arg_int)
130 isl_id_free(arg->id);
131 if (arg->type != pet_arg_array)
132 return;
133 for (type = pet_expr_access_begin; type < pet_expr_access_end; ++type)
134 arg->access[type] = isl_union_map_free(arg->access[type]);
137 /* Free a reference to "summary".
139 __isl_null pet_function_summary *pet_function_summary_free(
140 __isl_take pet_function_summary *summary)
142 int i;
144 if (!summary)
145 return NULL;
146 if (--summary->ref > 0)
147 return NULL;
149 for (i = 0; i < summary->n; ++i)
150 free_arg(&summary->arg[i]);
152 isl_ctx_deref(summary->ctx);
153 free(summary);
154 return NULL;
157 /* Return the number of arguments of the function summarized by "summary".
159 int pet_function_summary_get_n_arg(__isl_keep pet_function_summary *summary)
161 if (!summary)
162 return -1;
164 return summary->n;
167 /* Mark the argument at position "pos" of "summary" as an integer argument
168 * with the given identifier.
170 __isl_give pet_function_summary *pet_function_summary_set_int(
171 __isl_take pet_function_summary *summary, int pos,
172 __isl_take isl_id *id)
174 if (!summary || !id)
175 goto error;
177 if (pos < 0 || pos >= summary->n)
178 isl_die(summary->ctx, isl_error_invalid,
179 "position out of bounds", goto error);
181 free_arg(&summary->arg[pos]);
183 summary->arg[pos].type = pet_arg_int;
184 summary->arg[pos].id = id;
186 return summary;
187 error:
188 isl_id_free(id);
189 return pet_function_summary_free(summary);
192 /* Mark the argument at position "pos" of "summary" as an array argument
193 * with the given sets of accessed elements.
194 * The integer arguments of "summary" may appear as parameters
195 * in these sets of accessed elements.
196 * These parameters are turned into input dimensions of
197 * the corresponding access relations, which are then associated
198 * to the array argument.
199 * The order of the input dimensions is the same as the order
200 * in which the integer arguments appear in the sequence of arguments.
202 __isl_give pet_function_summary *pet_function_summary_set_array(
203 __isl_take pet_function_summary *summary, int pos,
204 __isl_take isl_union_set *may_read, __isl_take isl_union_set *may_write,
205 __isl_take isl_union_set *must_write)
207 int i, n;
208 isl_space *space;
209 enum pet_expr_access_type type;
211 if (!summary || !may_read || !may_write || !must_write)
212 goto error;
214 if (pos < 0 || pos >= summary->n)
215 isl_die(summary->ctx, isl_error_invalid,
216 "position out of bounds", goto error);
218 n = 0;
219 for (i = 0; i < summary->n; ++i)
220 if (pet_function_summary_arg_is_int(summary, i))
221 n++;
223 space = isl_space_params_alloc(summary->ctx, n);
225 n = 0;
226 for (i = 0; i < summary->n; ++i)
227 if (pet_function_summary_arg_is_int(summary, i))
228 space = isl_space_set_dim_id(space, isl_dim_param, n++,
229 isl_id_copy(summary->arg[i].id));
231 free_arg(&summary->arg[pos]);
233 summary->arg[pos].type = pet_arg_array;
234 summary->arg[pos].access[pet_expr_access_may_read] =
235 isl_union_map_from_range(may_read);
236 summary->arg[pos].access[pet_expr_access_may_write] =
237 isl_union_map_from_range(may_write);
238 summary->arg[pos].access[pet_expr_access_must_write] =
239 isl_union_map_from_range(must_write);
241 for (type = pet_expr_access_begin; type < pet_expr_access_end; ++type) {
242 isl_union_map *umap;
243 umap = summary->arg[pos].access[type];
244 umap = isl_union_map_align_params(umap, isl_space_copy(space));
245 umap = pet_union_map_move_dims(umap, isl_dim_in, 0,
246 isl_dim_param, 0, n);
247 summary->arg[pos].access[type] = umap;
248 if (!umap)
249 break;
252 isl_space_free(space);
254 if (type < pet_expr_access_end)
255 return pet_function_summary_free(summary);
257 return summary;
258 error:
259 isl_union_set_free(may_read);
260 isl_union_set_free(may_write);
261 isl_union_set_free(must_write);
262 return pet_function_summary_free(summary);
265 /* Has the argument of "summary" at position "pos" been marked
266 * as an integer argument?
268 int pet_function_summary_arg_is_int(__isl_keep pet_function_summary *summary,
269 int pos)
271 if (!summary)
272 return -1;
274 if (pos < 0 || pos >= summary->n)
275 isl_die(summary->ctx, isl_error_invalid,
276 "position out of bounds", return -1);
278 return summary->arg[pos].type == pet_arg_int;
281 /* Has the argument of "summary" at position "pos" been marked
282 * as an array argument?
284 int pet_function_summary_arg_is_array(__isl_keep pet_function_summary *summary,
285 int pos)
287 if (!summary)
288 return -1;
290 if (pos < 0 || pos >= summary->n)
291 isl_die(summary->ctx, isl_error_invalid,
292 "position out of bounds", return -1);
294 return summary->arg[pos].type == pet_arg_array;
297 /* Return the access relation of type "type" associated to
298 * the argument of "summary" at position "pos", which is assumed
299 * to be an array argument.
301 __isl_give isl_union_map *pet_function_summary_arg_get_access(
302 __isl_keep pet_function_summary *summary, int pos,
303 enum pet_expr_access_type type)
305 if (!summary)
306 return NULL;
307 if (pos < 0 || pos >= summary->n)
308 isl_die(summary->ctx, isl_error_invalid,
309 "position out of bounds", return NULL);
310 if (summary->arg[pos].type != pet_arg_array)
311 isl_die(summary->ctx, isl_error_invalid,
312 "not an array argument", return NULL);
314 return isl_union_map_copy(summary->arg[pos].access[type]);
317 /* Print "summary" to "p" in YAML format.
319 __isl_give isl_printer *pet_function_summary_print(
320 __isl_keep pet_function_summary *summary, __isl_take isl_printer *p)
322 int i;
324 if (!summary || !p)
325 return isl_printer_free(p);
326 p = isl_printer_yaml_start_sequence(p);
327 for (i = 0; i < summary->n; ++i) {
328 switch (summary->arg[i].type) {
329 case pet_arg_int:
330 p = isl_printer_yaml_start_mapping(p);
331 p = isl_printer_print_str(p, "id");
332 p = isl_printer_yaml_next(p);
333 p = isl_printer_print_id(p, summary->arg[i].id);
334 p = isl_printer_yaml_next(p);
335 p = isl_printer_yaml_end_mapping(p);
336 break;
337 case pet_arg_other:
338 p = isl_printer_print_str(p, "other");
339 break;
340 case pet_arg_array:
341 p = isl_printer_yaml_start_mapping(p);
342 p = isl_printer_print_str(p, "may_read");
343 p = isl_printer_yaml_next(p);
344 p = isl_printer_print_union_map(p,
345 summary->arg[i].access[pet_expr_access_may_read]);
346 p = isl_printer_yaml_next(p);
347 p = isl_printer_print_str(p, "may_write");
348 p = isl_printer_yaml_next(p);
349 p = isl_printer_print_union_map(p,
350 summary->arg[i].access[pet_expr_access_may_write]);
351 p = isl_printer_yaml_next(p);
352 p = isl_printer_print_str(p, "must_write");
353 p = isl_printer_yaml_next(p);
354 p = isl_printer_print_union_map(p,
355 summary->arg[i].access[pet_expr_access_must_write]);
356 p = isl_printer_yaml_next(p);
357 p = isl_printer_yaml_end_mapping(p);
358 break;
361 p = isl_printer_yaml_end_sequence(p);
363 return p;
366 /* Dump "summary" to stderr.
368 void pet_function_summary_dump(__isl_keep pet_function_summary *summary)
370 isl_printer *p;
372 if (!summary)
373 return;
375 p = isl_printer_to_file(pet_function_summary_get_ctx(summary), stderr);
376 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
377 p = pet_function_summary_print(summary, p);
379 isl_printer_free(p);