m4/ax_detect_clang.m4: check presence of clang/Basic/LangStandard.h
[pet.git] / summary.c
blob1a53baf85662388714f2d18d84066765e5b327b4
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/ctx.h>
35 #include <isl/printer.h>
36 #include <isl/id.h>
37 #include <isl/space.h>
38 #include <isl/union_set.h>
39 #include <isl/union_map.h>
41 #include "aff.h"
42 #include "summary.h"
44 /* A pet_function_summary objects represents an argument of a function.
46 * If "type" is pet_arg_int, then the argument has an integer type and
47 * can be used to describe the accesses performed by the pet_arg_array
48 * arguments. In this case, "id" refers to the formal argument.
50 * If "type" is pet_arg_array, then we keep track of the accesses
51 * through this argument in the access relations in "access".
52 * The domains of these access relations refer to the integer arguments
53 * of the function. That is, the input dimensions correspond
54 * to the arguments of type pet_arg_int.
56 * If "type" is pet_arg_other, then we do not keep track of any
57 * further information.
59 struct pet_function_summary_arg {
60 enum pet_arg_type type;
62 union {
63 isl_id *id;
64 isl_union_map *access[pet_expr_access_end];
68 /* A pet_function_summary object keeps track of the accesses performed
69 * by a function in terms of the function arguments.
71 * "n" is the number of arguments.
72 * "arg" contains a description of the "n" arguments.
74 struct pet_function_summary {
75 int ref;
76 isl_ctx *ctx;
78 unsigned n;
80 struct pet_function_summary_arg arg[];
83 /* Construct and return a new pet_function_summary object with
84 * "n_arg" arguments, initialized to pet_arg_other.
86 __isl_give pet_function_summary *pet_function_summary_alloc(isl_ctx *ctx,
87 unsigned n_arg)
89 pet_function_summary *summary;
90 int i;
92 summary = isl_calloc(ctx, struct pet_function_summary,
93 sizeof(struct pet_function_summary) +
94 n_arg * sizeof(struct pet_function_summary_arg));
95 if (!summary)
96 return summary;
98 summary->ctx = ctx;
99 isl_ctx_ref(ctx);
100 summary->ref = 1;
101 summary->n = n_arg;
102 for (i = 0; i < n_arg; ++i)
103 summary->arg[i].type = pet_arg_other;
105 return summary;
108 /* Return an extra reference to "summary".
110 __isl_give pet_function_summary *pet_function_summary_copy(
111 __isl_keep pet_function_summary *summary)
113 if (!summary)
114 return NULL;
116 summary->ref++;
117 return summary;
120 /* Return the isl_ctx in which "summary" was created.
122 isl_ctx *pet_function_summary_get_ctx(__isl_keep pet_function_summary *summary)
124 return summary ? summary->ctx : NULL;
127 /* Free the data stored in "arg".
129 static void free_arg(struct pet_function_summary_arg *arg)
131 enum pet_expr_access_type type;
133 if (arg->type == pet_arg_int)
134 isl_id_free(arg->id);
135 if (arg->type != pet_arg_array)
136 return;
137 for (type = pet_expr_access_begin; type < pet_expr_access_end; ++type)
138 arg->access[type] = isl_union_map_free(arg->access[type]);
141 /* Free a reference to "summary".
143 __isl_null pet_function_summary *pet_function_summary_free(
144 __isl_take pet_function_summary *summary)
146 int i;
148 if (!summary)
149 return NULL;
150 if (--summary->ref > 0)
151 return NULL;
153 for (i = 0; i < summary->n; ++i)
154 free_arg(&summary->arg[i]);
156 isl_ctx_deref(summary->ctx);
157 free(summary);
158 return NULL;
161 /* Return the number of arguments of the function summarized by "summary".
163 int pet_function_summary_get_n_arg(__isl_keep pet_function_summary *summary)
165 if (!summary)
166 return -1;
168 return summary->n;
171 /* Mark the argument at position "pos" of "summary" as an integer argument
172 * with the given identifier.
174 __isl_give pet_function_summary *pet_function_summary_set_int(
175 __isl_take pet_function_summary *summary, int pos,
176 __isl_take isl_id *id)
178 if (!summary || !id)
179 goto error;
181 if (pos < 0 || pos >= summary->n)
182 isl_die(summary->ctx, isl_error_invalid,
183 "position out of bounds", goto error);
185 free_arg(&summary->arg[pos]);
187 summary->arg[pos].type = pet_arg_int;
188 summary->arg[pos].id = id;
190 return summary;
191 error:
192 isl_id_free(id);
193 return pet_function_summary_free(summary);
196 /* Mark the argument at position "pos" of "summary" as an array argument
197 * with the given sets of accessed elements.
198 * The integer arguments of "summary" may appear as parameters
199 * in these sets of accessed elements.
200 * These parameters are turned into input dimensions of
201 * the corresponding access relations, which are then associated
202 * to the array argument.
203 * The order of the input dimensions is the same as the order
204 * in which the integer arguments appear in the sequence of arguments.
206 __isl_give pet_function_summary *pet_function_summary_set_array(
207 __isl_take pet_function_summary *summary, int pos,
208 __isl_take isl_union_set *may_read, __isl_take isl_union_set *may_write,
209 __isl_take isl_union_set *must_write)
211 int i, n;
212 isl_space *space;
213 enum pet_expr_access_type type;
215 if (!summary || !may_read || !may_write || !must_write)
216 goto error;
218 if (pos < 0 || pos >= summary->n)
219 isl_die(summary->ctx, isl_error_invalid,
220 "position out of bounds", goto error);
222 n = 0;
223 for (i = 0; i < summary->n; ++i)
224 if (pet_function_summary_arg_is_int(summary, i))
225 n++;
227 space = isl_space_params_alloc(summary->ctx, n);
229 n = 0;
230 for (i = 0; i < summary->n; ++i)
231 if (pet_function_summary_arg_is_int(summary, i))
232 space = isl_space_set_dim_id(space, isl_dim_param, n++,
233 isl_id_copy(summary->arg[i].id));
235 free_arg(&summary->arg[pos]);
237 summary->arg[pos].type = pet_arg_array;
238 summary->arg[pos].access[pet_expr_access_may_read] =
239 isl_union_map_from_range(may_read);
240 summary->arg[pos].access[pet_expr_access_may_write] =
241 isl_union_map_from_range(may_write);
242 summary->arg[pos].access[pet_expr_access_must_write] =
243 isl_union_map_from_range(must_write);
245 for (type = pet_expr_access_begin; type < pet_expr_access_end; ++type) {
246 isl_union_map *umap;
247 umap = summary->arg[pos].access[type];
248 umap = isl_union_map_align_params(umap, isl_space_copy(space));
249 umap = pet_union_map_move_dims(umap, isl_dim_in, 0,
250 isl_dim_param, 0, n);
251 summary->arg[pos].access[type] = umap;
252 if (!umap)
253 break;
256 isl_space_free(space);
258 if (type < pet_expr_access_end)
259 return pet_function_summary_free(summary);
261 return summary;
262 error:
263 isl_union_set_free(may_read);
264 isl_union_set_free(may_write);
265 isl_union_set_free(must_write);
266 return pet_function_summary_free(summary);
269 /* Has the argument of "summary" at position "pos" been marked
270 * as an integer argument?
272 int pet_function_summary_arg_is_int(__isl_keep pet_function_summary *summary,
273 int pos)
275 if (!summary)
276 return -1;
278 if (pos < 0 || pos >= summary->n)
279 isl_die(summary->ctx, isl_error_invalid,
280 "position out of bounds", return -1);
282 return summary->arg[pos].type == pet_arg_int;
285 /* Has the argument of "summary" at position "pos" been marked
286 * as an array argument?
288 int pet_function_summary_arg_is_array(__isl_keep pet_function_summary *summary,
289 int pos)
291 if (!summary)
292 return -1;
294 if (pos < 0 || pos >= summary->n)
295 isl_die(summary->ctx, isl_error_invalid,
296 "position out of bounds", return -1);
298 return summary->arg[pos].type == pet_arg_array;
301 /* Return the access relation of type "type" associated to
302 * the argument of "summary" at position "pos", which is assumed
303 * to be an array argument.
305 __isl_give isl_union_map *pet_function_summary_arg_get_access(
306 __isl_keep pet_function_summary *summary, int pos,
307 enum pet_expr_access_type type)
309 if (!summary)
310 return NULL;
311 if (pos < 0 || pos >= summary->n)
312 isl_die(summary->ctx, isl_error_invalid,
313 "position out of bounds", return NULL);
314 if (summary->arg[pos].type != pet_arg_array)
315 isl_die(summary->ctx, isl_error_invalid,
316 "not an array argument", return NULL);
318 return isl_union_map_copy(summary->arg[pos].access[type]);
321 /* Print "summary" to "p" in YAML format.
323 __isl_give isl_printer *pet_function_summary_print(
324 __isl_keep pet_function_summary *summary, __isl_take isl_printer *p)
326 int i;
328 if (!summary || !p)
329 return isl_printer_free(p);
330 p = isl_printer_yaml_start_sequence(p);
331 for (i = 0; i < summary->n; ++i) {
332 switch (summary->arg[i].type) {
333 case pet_arg_int:
334 p = isl_printer_yaml_start_mapping(p);
335 p = isl_printer_print_str(p, "id");
336 p = isl_printer_yaml_next(p);
337 p = isl_printer_print_id(p, summary->arg[i].id);
338 p = isl_printer_yaml_next(p);
339 p = isl_printer_yaml_end_mapping(p);
340 break;
341 case pet_arg_other:
342 p = isl_printer_print_str(p, "other");
343 break;
344 case pet_arg_array:
345 p = isl_printer_yaml_start_mapping(p);
346 p = isl_printer_print_str(p, "may_read");
347 p = isl_printer_yaml_next(p);
348 p = isl_printer_print_union_map(p,
349 summary->arg[i].access[pet_expr_access_may_read]);
350 p = isl_printer_yaml_next(p);
351 p = isl_printer_print_str(p, "may_write");
352 p = isl_printer_yaml_next(p);
353 p = isl_printer_print_union_map(p,
354 summary->arg[i].access[pet_expr_access_may_write]);
355 p = isl_printer_yaml_next(p);
356 p = isl_printer_print_str(p, "must_write");
357 p = isl_printer_yaml_next(p);
358 p = isl_printer_print_union_map(p,
359 summary->arg[i].access[pet_expr_access_must_write]);
360 p = isl_printer_yaml_next(p);
361 p = isl_printer_yaml_end_mapping(p);
362 break;
365 p = isl_printer_yaml_end_sequence(p);
367 return p;
370 /* Dump "summary" to stderr.
372 void pet_function_summary_dump(__isl_keep pet_function_summary *summary)
374 isl_printer *p;
376 if (!summary)
377 return;
379 p = isl_printer_to_file(pet_function_summary_get_ctx(summary), stderr);
380 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
381 p = pet_function_summary_print(summary, p);
383 isl_printer_free(p);