gpu_group.c: can_tile: return isl_bool
[ppcg.git] / print.c
blobb64a7c3e0f178763f0b5ac7b4be9821998730216
1 /*
2 * Copyright 2012-2013 Ecole Normale Superieure
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege,
7 * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
8 */
10 #include <isl/ctx.h>
11 #include <isl/id.h>
12 #include <isl/aff.h>
13 #include <isl/ast.h>
14 #include <isl/ast_build.h>
15 #include <isl/printer.h>
17 #include "print.h"
18 #include "util.h"
20 __isl_give isl_printer *ppcg_start_block(__isl_take isl_printer *p)
22 p = isl_printer_start_line(p);
23 p = isl_printer_print_str(p, "{");
24 p = isl_printer_end_line(p);
25 p = isl_printer_indent(p, 2);
26 return p;
29 __isl_give isl_printer *ppcg_end_block(__isl_take isl_printer *p)
31 p = isl_printer_indent(p, -2);
32 p = isl_printer_start_line(p);
33 p = isl_printer_print_str(p, "}");
34 p = isl_printer_end_line(p);
35 return p;
38 /* Names of notes that keep track of whether min/max
39 * macro definitions have already been printed.
41 static const char *ppcg_max_printed = "ppcg_max_printed";
42 static const char *ppcg_min_printed = "ppcg_min_printed";
44 /* Has the macro definition corresponding to "note_name" been printed
45 * to "p" before?
46 * That is, does "p" have an associated "note_name" note?
48 static isl_bool printed_before(__isl_keep isl_printer *p, const char *note_name)
50 isl_ctx *ctx;
51 isl_id *id;
52 isl_bool printed;
54 if (!p)
55 return isl_bool_error;
57 ctx = isl_printer_get_ctx(p);
58 id = isl_id_alloc(ctx, note_name, NULL);
59 printed = isl_printer_has_note(p, id);
60 isl_id_free(id);
62 return printed;
65 /* Keep track of the fact that the macro definition corresponding
66 * to "note_name" has been printed to "p" by attaching a note with
67 * that name. The value of the note is of no importance, but it
68 * has to be a valid isl_id, so the note identifier is reused
69 * as the note.
71 static __isl_give isl_printer *mark_printed(__isl_take isl_printer *p,
72 const char *note_name)
74 isl_ctx *ctx;
75 isl_id *id;
77 if (!p)
78 return NULL;
80 ctx = isl_printer_get_ctx(p);
81 id = isl_id_alloc(ctx, note_name, NULL);
82 return isl_printer_set_note(p, id, isl_id_copy(id));
85 /* Print a macro definition "def" for the macro "name" to "p",
86 * unless such a macro definition has been printed to "p" before.
87 * "note_name" is used as the name of the note that keeps track
88 * of whether this printing has happened.
90 static __isl_give isl_printer *print_ppcg_macro(__isl_take isl_printer *p,
91 const char *name, const char *def, const char *note_name)
93 isl_bool printed;
95 printed = printed_before(p, note_name);
96 if (printed < 0)
97 return isl_printer_free(p);
98 if (printed)
99 return p;
101 p = isl_printer_start_line(p);
102 p = isl_printer_print_str(p, "#define ");
103 p = isl_printer_print_str(p, name);
104 p = isl_printer_print_str(p, def);
105 p = isl_printer_end_line(p);
107 p = mark_printed(p, note_name);
109 return p;
112 /* Structure for keeping track of definitions of some macros.
114 struct ppcg_macros {
115 const char *min;
116 const char *max;
119 /* Free the memory allocated by a struct ppcg_macros.
121 static void ppcg_macros_free(void *user)
123 free(user);
126 /* Default macro definitions (when GNU extensions are allowed).
128 struct ppcg_macros ppcg_macros_default = {
129 .min = "(x,y) "
130 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
131 "_x < _y ? _x : _y; })",
132 .max = "(x,y) "
133 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
134 "_x > _y ? _x : _y; })",
137 /* Name used for the note that keeps track of macro definitions.
139 static const char *ppcg_macros = "ppcg_macros";
141 /* Set the macro definitions for isl_ast_op_min and isl_ast_op_max
142 * to "min" and "max" and store them in "p".
144 * In particular, create a ppcg_macros object and attach it
145 * as a note to the printer.
147 __isl_give isl_printer *ppcg_set_macros(__isl_take isl_printer *p,
148 const char *min, const char *max)
150 isl_ctx *ctx;
151 isl_id *id, *macros_id;
152 struct ppcg_macros *macros;
154 if (!p)
155 return NULL;
157 ctx = isl_printer_get_ctx(p);
158 macros = isl_alloc_type(ctx, struct ppcg_macros);
159 if (!macros)
160 return isl_printer_free(p);
161 macros->min = min;
162 macros->max = max;
163 id = isl_id_alloc(ctx, ppcg_macros, NULL);
164 macros_id = isl_id_alloc(ctx, NULL, macros);
165 if (!macros_id)
166 ppcg_macros_free(macros);
167 else
168 macros_id = isl_id_set_free_user(macros_id, &ppcg_macros_free);
170 p = isl_printer_set_note(p, id, macros_id);
172 return p;
175 /* Return the ppcg_macros object that holds the currently active
176 * macro definitions in "p".
177 * If "p" has a note with macro definitions, then return those.
178 * Otherwise, return the default macro definitions.
180 static struct ppcg_macros *get_macros(__isl_keep isl_printer *p)
182 isl_id *id;
183 isl_bool has_macros;
184 struct ppcg_macros *macros;
186 id = isl_id_alloc(isl_printer_get_ctx(p), ppcg_macros, NULL);
187 has_macros = isl_printer_has_note(p, id);
188 if (has_macros < 0 || !has_macros) {
189 isl_id_free(id);
190 if (has_macros < 0)
191 return NULL;
192 return &ppcg_macros_default;
194 id = isl_printer_get_note(p, id);
195 macros = isl_id_get_user(id);
196 isl_id_free(id);
198 return macros;
201 /* Print the currently active macro definition for ppcg_max.
203 static __isl_give isl_printer *print_max(__isl_take isl_printer *p)
205 struct ppcg_macros *macros;
207 macros = get_macros(p);
208 if (!macros)
209 return isl_printer_free(p);
210 return print_ppcg_macro(p, ppcg_max, macros->max, ppcg_max_printed);
213 /* Print the currently active macro definition for ppcg_min.
215 static __isl_give isl_printer *print_min(__isl_take isl_printer *p)
217 struct ppcg_macros *macros;
219 macros = get_macros(p);
220 if (!macros)
221 return isl_printer_free(p);
222 return print_ppcg_macro(p, ppcg_min, macros->min, ppcg_min_printed);
225 /* Print a macro definition for "type" to "p".
226 * If GNU extensions are allowed, then print a specialized definition
227 * for isl_ast_op_min and isl_ast_op_max.
228 * Otherwise, use the default isl definition.
230 __isl_give isl_printer *ppcg_print_macro(enum isl_ast_op_type type,
231 __isl_take isl_printer *p)
233 isl_ctx *ctx;
234 struct ppcg_options *options;
236 if (!p)
237 return NULL;
239 ctx = isl_printer_get_ctx(p);
240 options = isl_ctx_peek_options(ctx, &ppcg_options_args);
241 if (!options || !options->allow_gnu_extensions)
242 return isl_ast_op_type_print_macro(type, p);
244 switch (type) {
245 case isl_ast_op_max:
246 return print_max(p);
247 case isl_ast_op_min:
248 return print_min(p);
249 default:
250 return isl_ast_op_type_print_macro(type, p);
254 /* isl_ast_expr_foreach_ast_op_type or isl_ast_node_foreach_ast_op_type
255 * callback that prints a macro definition for "type".
257 static isl_stat print_macro(enum isl_ast_op_type type, void *user)
259 isl_printer **p = user;
261 *p = ppcg_print_macro(type, *p);
262 if (!*p)
263 return isl_stat_error;
265 return isl_stat_ok;
268 /* Print the required macros for "expr".
270 __isl_give isl_printer *ppcg_ast_expr_print_macros(
271 __isl_keep isl_ast_expr *expr, __isl_take isl_printer *p)
273 if (isl_ast_expr_foreach_ast_op_type(expr, &print_macro, &p) < 0)
274 return isl_printer_free(p);
275 return p;
278 /* isl_id_to_ast_expr_foreach callback that prints the required
279 * macro definitions for "val".
281 static isl_stat print_expr_macros(__isl_take isl_id *key,
282 __isl_take isl_ast_expr *val, void *user)
284 isl_printer **p = user;
286 *p = ppcg_ast_expr_print_macros(val, *p);
287 isl_id_free(key);
288 isl_ast_expr_free(val);
290 if (!*p)
291 return isl_stat_error;
292 return isl_stat_ok;
295 /* Print the required macro definitions for the body of a statement in which
296 * the access expressions are replaced by the isl_ast_expr objects
297 * in "ref2expr".
299 __isl_give isl_printer *ppcg_print_body_macros(__isl_take isl_printer *p,
300 __isl_keep isl_id_to_ast_expr *ref2expr)
302 if (isl_id_to_ast_expr_foreach(ref2expr, &print_expr_macros, &p) < 0)
303 return isl_printer_free(p);
304 return p;
307 /* Print the required macros for "node".
309 __isl_give isl_printer *ppcg_print_macros(__isl_take isl_printer *p,
310 __isl_keep isl_ast_node *node)
312 if (isl_ast_node_foreach_ast_op_type(node, &print_macro, &p) < 0)
313 return isl_printer_free(p);
314 return p;
317 /* Names used for the macros that may appear in a printed isl AST.
319 const char *ppcg_min = "ppcg_min";
320 const char *ppcg_max = "ppcg_max";
321 const char *ppcg_fdiv_q = "ppcg_fdiv_q";
323 /* Set the names of the macros that may appear in a printed isl AST.
325 __isl_give isl_printer *ppcg_set_macro_names(__isl_take isl_printer *p)
327 p = isl_ast_op_type_set_print_name(p, isl_ast_op_min, ppcg_min);
328 p = isl_ast_op_type_set_print_name(p, isl_ast_op_max, ppcg_max);
329 p = isl_ast_op_type_set_print_name(p, isl_ast_op_fdiv_q, ppcg_fdiv_q);
331 return p;
334 /* Given a multi affine expression "mpa" without domain, modify it to have
335 * the schedule space of "build" as domain.
337 * If the schedule space of "build" is a parameter space, then nothing
338 * needs to be done.
339 * Otherwise, "mpa" is first given a 0D domain and then it is combined
340 * with a mapping from the schedule space of "build" to the same 0D domain.
342 __isl_give isl_multi_pw_aff *ppcg_attach_multi_pw_aff(
343 __isl_take isl_multi_pw_aff *mpa, __isl_keep isl_ast_build *build)
345 isl_bool params;
346 isl_space *space;
347 isl_multi_aff *ma;
349 space = isl_ast_build_get_schedule_space(build);
350 params = isl_space_is_params(space);
351 if (params < 0 || params) {
352 isl_space_free(space);
353 if (params < 0)
354 return isl_multi_pw_aff_free(mpa);
355 return mpa;
357 space = isl_space_from_domain(space);
358 ma = isl_multi_aff_zero(space);
359 mpa = isl_multi_pw_aff_from_range(mpa);
360 mpa = isl_multi_pw_aff_pullback_multi_aff(mpa, ma);
362 return mpa;
365 /* Build an access AST expression from "size" using "build".
366 * "size" does not have a domain, but "build" may have a proper schedule space.
367 * First modify "size" to have that schedule space as domain.
369 __isl_give isl_ast_expr *ppcg_build_size_expr(__isl_take isl_multi_pw_aff *size,
370 __isl_keep isl_ast_build *build)
372 size = ppcg_attach_multi_pw_aff(size, build);
373 return isl_ast_build_access_from_multi_pw_aff(build, size);
376 /* Print a declaration for an array with element type "base_type" and
377 * size "size" to "p".
379 __isl_give isl_printer *ppcg_print_declaration_with_size(
380 __isl_take isl_printer *p, const char *base_type,
381 __isl_keep isl_ast_expr *size)
383 if (!base_type || !size)
384 return isl_printer_free(p);
386 p = ppcg_ast_expr_print_macros(size, p);
387 p = isl_printer_start_line(p);
388 p = isl_printer_print_str(p, base_type);
389 p = isl_printer_print_str(p, " ");
390 p = isl_printer_print_ast_expr(p, size);
391 p = isl_printer_print_str(p, ";");
392 p = isl_printer_end_line(p);
394 return p;
397 /* Print a declaration for array "array" to "p", using "build"
398 * to simplify any size expressions.
400 * The size is computed from the extent of the array and is
401 * subsequently converted to an "access expression" by "build".
403 __isl_give isl_printer *ppcg_print_declaration(__isl_take isl_printer *p,
404 struct pet_array *array, __isl_keep isl_ast_build *build)
406 isl_multi_pw_aff *size;
407 isl_ast_expr *expr;
409 if (!array)
410 return isl_printer_free(p);
412 size = ppcg_size_from_extent(isl_set_copy(array->extent));
413 expr = isl_ast_build_access_from_multi_pw_aff(build, size);
414 p = ppcg_print_declaration_with_size(p, array->element_type, expr);
415 isl_ast_expr_free(expr);
417 return p;
420 /* Print declarations for the arrays in "scop" that are declared
421 * and that are exposed (if exposed == 1) or not exposed (if exposed == 0).
423 static __isl_give isl_printer *print_declarations(__isl_take isl_printer *p,
424 struct ppcg_scop *scop, int exposed)
426 int i;
427 isl_ast_build *build;
429 if (!scop)
430 return isl_printer_free(p);
432 build = isl_ast_build_from_context(isl_set_copy(scop->context));
433 for (i = 0; i < scop->pet->n_array; ++i) {
434 struct pet_array *array = scop->pet->arrays[i];
436 if (!array->declared)
437 continue;
438 if (array->exposed != exposed)
439 continue;
441 p = ppcg_print_declaration(p, array, build);
443 isl_ast_build_free(build);
445 return p;
448 /* Print declarations for the arrays in "scop" that are declared
449 * and exposed to the code after the scop.
451 __isl_give isl_printer *ppcg_print_exposed_declarations(
452 __isl_take isl_printer *p, struct ppcg_scop *scop)
454 return print_declarations(p, scop, 1);
457 /* Print declarations for the arrays in "scop" that are declared,
458 * but not exposed to the code after the scop.
460 __isl_give isl_printer *ppcg_print_hidden_declarations(
461 __isl_take isl_printer *p, struct ppcg_scop *scop)
463 return print_declarations(p, scop, 0);