tree2scop.c: scop_from_tree_macro: drop redundant argument and plug leak
[pet.git] / pet_codegen.c
blob2535d8c6f19db66fecb4d074ec553febafde00b4
1 /*
2 * Copyright 2012-2013 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 <assert.h>
35 #include <isl/aff.h>
36 #include <isl/ast_build.h>
37 #include <isl/options.h>
38 #include <isl/set.h>
39 #include <isl/map.h>
40 #include <isl/union_set.h>
41 #include <isl/schedule_node.h>
43 struct options {
44 struct isl_options *isl;
45 unsigned tree;
46 unsigned atomic;
47 unsigned separate;
48 unsigned read_options;
51 ISL_ARGS_START(struct options, options_args)
52 ISL_ARG_CHILD(struct options, isl, "isl", &isl_options_args, "isl options")
53 ISL_ARG_BOOL(struct options, tree, 0, "tree", 0,
54 "input schedule is specified as schedule tree")
55 ISL_ARG_BOOL(struct options, atomic, 0, "atomic", 0,
56 "globally set the atomic option")
57 ISL_ARG_BOOL(struct options, separate, 0, "separate", 0,
58 "globally set the separate option")
59 ISL_ARG_BOOL(struct options, read_options, 0, "read-options", 0,
60 "read options from standard input")
61 ISL_ARGS_END
63 ISL_ARG_DEF(options, struct options, options_args)
65 /* Return a universal, 1-dimensional set with the given name.
67 static __isl_give isl_union_set *universe(isl_ctx *ctx, const char *name)
69 isl_space *space;
71 space = isl_space_set_alloc(ctx, 0, 1);
72 space = isl_space_set_tuple_name(space, isl_dim_set, name);
73 return isl_union_set_from_set(isl_set_universe(space));
76 /* Set the "name" option for the entire schedule domain.
78 static __isl_give isl_union_map *set_universe(__isl_take isl_union_map *opt,
79 __isl_keep isl_union_map *schedule, const char *name)
81 isl_ctx *ctx;
82 isl_union_set *domain, *target;
83 isl_union_map *option;
85 ctx = isl_union_map_get_ctx(opt);
87 domain = isl_union_map_range(isl_union_map_copy(schedule));
88 domain = isl_union_set_universe(domain);
89 target = universe(ctx, name);
90 option = isl_union_map_from_domain_and_range(domain, target);
91 opt = isl_union_map_union(opt, option);
93 return opt;
96 /* Set the build options based on the command line options.
98 * If no command line options are specified, we use default build options.
99 * If --read-options is specified, we read the build options from standard
100 * input.
101 * If --separate or --atomic is specified, we turn on the corresponding
102 * build option over the entire schedule domain.
104 static __isl_give isl_ast_build *set_options(__isl_take isl_ast_build *build,
105 struct options *options, __isl_keep isl_union_map *schedule)
107 isl_ctx *ctx;
108 isl_space *space;
109 isl_union_set *domain, *separate;
110 isl_union_map *opt, *opt_s, *opt_a;
112 if (!options->separate && !options->atomic && !options->read_options)
113 return build;
115 ctx = isl_union_map_get_ctx(schedule);
117 if (options->read_options)
118 opt = isl_union_map_read_from_file(ctx, stdin);
119 else
120 opt = isl_union_map_empty(isl_union_map_get_space(schedule));
122 if (options->separate)
123 opt = set_universe(opt, schedule, "separate");
124 if (options->atomic)
125 opt = set_universe(opt, schedule, "atomic");
127 build = isl_ast_build_set_options(build, opt);
129 return build;
132 /* Print a function declaration for the domain "set".
134 * In particular, print a declaration of the form
136 * void S(int, ..., int);
138 * where S is the name of the domain and the number of arguments
139 * is equal to the dimension of "set".
141 static isl_stat print_declaration(__isl_take isl_set *set, void *user)
143 isl_printer **p = user;
144 int i, n;
146 n = isl_set_dim(set, isl_dim_set);
148 *p = isl_printer_start_line(*p);
149 *p = isl_printer_print_str(*p, "void ");
150 *p = isl_printer_print_str(*p, isl_set_get_tuple_name(set));
151 *p = isl_printer_print_str(*p, "(");
152 for (i = 0; i < n; ++i) {
153 if (i)
154 *p = isl_printer_print_str(*p, ", ");
155 *p = isl_printer_print_str(*p, "int");
157 *p = isl_printer_print_str(*p, ");");
158 *p = isl_printer_end_line(*p);
160 isl_set_free(set);
162 return isl_stat_ok;
165 /* Print a function declaration for each domain in "uset".
167 static __isl_give isl_printer *print_declarations(__isl_take isl_printer *p,
168 __isl_keep isl_union_set *uset)
170 if (isl_union_set_foreach_set(uset, &print_declaration, &p) >= 0)
171 return p;
172 isl_printer_free(p);
173 return NULL;
176 /* Check that the domain of "map" is named.
178 static isl_stat check_name(__isl_take isl_map *map, void *user)
180 int named;
181 isl_ctx *ctx;
183 ctx = isl_map_get_ctx(map);
184 named = isl_map_has_tuple_name(map, isl_dim_in);
185 isl_map_free(map);
187 if (named < 0)
188 return isl_stat_error;
189 if (!named)
190 isl_die(ctx, isl_error_invalid,
191 "all domains should be named", return isl_stat_error);
192 return isl_stat_ok;
195 /* Given an AST "tree", print out the following code
197 * void foo(<parameters>/)
199 * void S1(int,...,int);
200 * #pragma scop
201 * AST
202 * #pragma endscop
205 * where the declarations are derived from the spaces in "domain".
207 static void print_tree(__isl_take isl_union_set *domain,
208 __isl_take isl_ast_node *tree)
210 int i, n;
211 isl_ctx *ctx;
212 isl_space *space;
213 isl_printer *p;
214 isl_ast_print_options *print_options;
216 if (!domain || !tree)
217 goto error;
219 ctx = isl_union_set_get_ctx(domain);
221 p = isl_printer_to_file(ctx, stdout);
222 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
223 p = isl_printer_start_line(p);
224 p = isl_printer_print_str(p, "void foo(");
226 space = isl_union_set_get_space(domain);
227 n = isl_space_dim(space, isl_dim_param);
228 for (i = 0; i < n; ++i) {
229 const char *name;
231 if (i)
232 p = isl_printer_print_str(p, ", ");
233 name = isl_space_get_dim_name(space, isl_dim_param, i);
234 p = isl_printer_print_str(p, "int ");
235 p = isl_printer_print_str(p, name);
237 isl_space_free(space);
239 p = isl_printer_print_str(p, ")");
240 p = isl_printer_end_line(p);
241 p = isl_printer_start_line(p);
242 p = isl_printer_print_str(p, "{");
243 p = isl_printer_end_line(p);
244 p = isl_printer_start_line(p);
245 p = isl_printer_indent(p, 2);
246 p = print_declarations(p, domain);
247 p = isl_printer_indent(p, -2);
248 p = isl_printer_print_str(p, "#pragma scop");
249 p = isl_printer_end_line(p);
251 p = isl_printer_indent(p, 2);
252 print_options = isl_ast_print_options_alloc(ctx);
253 p = isl_ast_node_print(tree, p, print_options);
254 p = isl_printer_indent(p, -2);
255 p = isl_printer_start_line(p);
256 p = isl_printer_print_str(p, "#pragma endscop");
257 p = isl_printer_end_line(p);
258 p = isl_printer_start_line(p);
259 p = isl_printer_print_str(p, "}");
260 p = isl_printer_end_line(p);
261 isl_printer_free(p);
263 error:
264 isl_union_set_free(domain);
265 isl_ast_node_free(tree);
268 /* If "node" is a band node, then replace the AST build options
269 * by "options".
271 static __isl_give isl_schedule_node *node_set_options(
272 __isl_take isl_schedule_node *node, void *user)
274 enum isl_ast_loop_type *type = user;
275 int i, n;
277 if (isl_schedule_node_get_type(node) != isl_schedule_node_band)
278 return node;
280 n = isl_schedule_node_band_n_member(node);
281 for (i = 0; i < n; ++i)
282 node = isl_schedule_node_band_member_set_ast_loop_type(node,
283 i, *type);
284 return node;
287 /* Replace the AST build options on all band nodes if requested
288 * by the user.
290 static __isl_give isl_schedule *schedule_set_options(
291 __isl_take isl_schedule *schedule, struct options *options)
293 enum isl_ast_loop_type type;
295 if (!options->separate && !options->atomic)
296 return schedule;
298 type = options->separate ? isl_ast_loop_separate : isl_ast_loop_atomic;
299 schedule = isl_schedule_map_schedule_node_bottom_up(schedule,
300 &node_set_options, &type);
302 return schedule;
305 /* Read a schedule tree, generate an AST and print the result
306 * in a form that is readable by pet.
308 static int print_schedule_tree(isl_ctx *ctx, struct options *options)
310 isl_union_set *domain;
311 isl_schedule *schedule;
312 isl_ast_build *build;
313 isl_ast_node *tree;
315 schedule = isl_schedule_read_from_file(ctx, stdin);
316 domain = isl_schedule_get_domain(schedule);
318 build = isl_ast_build_alloc(ctx);
319 schedule = schedule_set_options(schedule, options);
320 tree = isl_ast_build_node_from_schedule(build, schedule);
321 isl_ast_build_free(build);
323 print_tree(domain, tree);
325 return 0;
328 /* Read a schedule, a context and (optionally) build options,
329 * generate an AST and print the result in a form that is readable
330 * by pet.
332 static int print_schedule_map(isl_ctx *ctx, struct options *options)
334 isl_set *context;
335 isl_union_set *domain;
336 isl_union_map *schedule;
337 isl_ast_build *build;
338 isl_ast_node *tree;
340 schedule = isl_union_map_read_from_file(ctx, stdin);
341 if (isl_union_map_foreach_map(schedule, &check_name, NULL) < 0) {
342 isl_union_map_free(schedule);
343 return 1;
345 context = isl_set_read_from_file(ctx, stdin);
347 domain = isl_union_map_domain(isl_union_map_copy(schedule));
348 domain = isl_union_set_align_params(domain, isl_set_get_space(context));
350 build = isl_ast_build_from_context(context);
351 build = set_options(build, options, schedule);
352 tree = isl_ast_build_node_from_schedule_map(build, schedule);
353 isl_ast_build_free(build);
355 print_tree(domain, tree);
357 return 0;
360 /* Read either
361 * - a schedule tree or
362 * - a schedule, a context and (optionally) build options,
363 * generate an AST and print the result in a form that is readable
364 * by pet.
366 int main(int argc, char **argv)
368 isl_ctx *ctx;
369 struct options *options;
370 int r;
372 options = options_new_with_defaults();
373 assert(options);
374 argc = options_parse(options, argc, argv, ISL_ARG_ALL);
376 ctx = isl_ctx_alloc_with_options(&options_args, options);
378 if (options->tree)
379 r = print_schedule_tree(ctx, options);
380 else
381 r = print_schedule_map(ctx, options);
383 isl_ctx_free(ctx);
384 return r;