print.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * Copyright 2012-2013 Ecole Normale Superieure
  3. *
  4. * Use of this software is governed by the MIT license
  5. *
  6. * Written by Sven Verdoolaege,
  7. * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
  8. */
  9. #include <isl/aff.h>
  10. #include <isl/ast_build.h>
  11. #include <isl/id.h>
  12. #include "print.h"
  13. #include "util.h"
  14. __isl_give isl_printer *ppcg_start_block(__isl_take isl_printer *p)
  15. {
  16. p = isl_printer_start_line(p);
  17. p = isl_printer_print_str(p, "{");
  18. p = isl_printer_end_line(p);
  19. p = isl_printer_indent(p, 2);
  20. return p;
  21. }
  22. __isl_give isl_printer *ppcg_end_block(__isl_take isl_printer *p)
  23. {
  24. p = isl_printer_indent(p, -2);
  25. p = isl_printer_start_line(p);
  26. p = isl_printer_print_str(p, "}");
  27. p = isl_printer_end_line(p);
  28. return p;
  29. }
  30. /* Names of notes that keep track of whether min/max
  31. * macro definitions have already been printed.
  32. */
  33. static const char *ppcg_max_printed = "ppcg_max_printed";
  34. static const char *ppcg_min_printed = "ppcg_min_printed";
  35. /* Has the macro definition corresponding to "note_name" been printed
  36. * to "p" before?
  37. * That is, does "p" have an associated "note_name" note?
  38. */
  39. static isl_bool printed_before(__isl_keep isl_printer *p, const char *note_name)
  40. {
  41. isl_ctx *ctx;
  42. isl_id *id;
  43. isl_bool printed;
  44. if (!p)
  45. return isl_bool_error;
  46. ctx = isl_printer_get_ctx(p);
  47. id = isl_id_alloc(ctx, note_name, NULL);
  48. printed = isl_printer_has_note(p, id);
  49. isl_id_free(id);
  50. return printed;
  51. }
  52. /* Keep track of the fact that the macro definition corresponding
  53. * to "note_name" has been printed to "p" by attaching a note with
  54. * that name. The value of the note is of no importance, but it
  55. * has to be a valid isl_id, so the note identifier is reused
  56. * as the note.
  57. */
  58. static __isl_give isl_printer *mark_printed(__isl_take isl_printer *p,
  59. const char *note_name)
  60. {
  61. isl_ctx *ctx;
  62. isl_id *id;
  63. if (!p)
  64. return NULL;
  65. ctx = isl_printer_get_ctx(p);
  66. id = isl_id_alloc(ctx, note_name, NULL);
  67. return isl_printer_set_note(p, id, isl_id_copy(id));
  68. }
  69. /* Print a macro definition "def" for the macro "name" to "p",
  70. * unless such a macro definition has been printed to "p" before.
  71. * "note_name" is used as the name of the note that keeps track
  72. * of whether this printing has happened.
  73. */
  74. static __isl_give isl_printer *print_ppcg_macro(__isl_take isl_printer *p,
  75. const char *name, const char *def, const char *note_name)
  76. {
  77. isl_bool printed;
  78. printed = printed_before(p, note_name);
  79. if (printed < 0)
  80. return isl_printer_free(p);
  81. if (printed)
  82. return p;
  83. p = isl_printer_start_line(p);
  84. p = isl_printer_print_str(p, "#define ");
  85. p = isl_printer_print_str(p, name);
  86. p = isl_printer_print_str(p, def);
  87. p = isl_printer_end_line(p);
  88. p = mark_printed(p, note_name);
  89. return p;
  90. }
  91. /* Structure for keeping track of definitions of some macros.
  92. */
  93. struct ppcg_macros {
  94. const char *min;
  95. const char *max;
  96. };
  97. /* Free the memory allocated by a struct ppcg_macros.
  98. */
  99. static void ppcg_macros_free(void *user)
  100. {
  101. free(user);
  102. }
  103. /* Default macro definitions (when GNU extensions are allowed).
  104. */
  105. struct ppcg_macros ppcg_macros_default = {
  106. .min = "(x,y) "
  107. "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
  108. "_x < _y ? _x : _y; })",
  109. .max = "(x,y) "
  110. "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
  111. "_x > _y ? _x : _y; })",
  112. };
  113. /* Name used for the note that keeps track of macro definitions.
  114. */
  115. static const char *ppcg_macros = "ppcg_macros";
  116. /* Set the macro definitions for isl_ast_op_min and isl_ast_op_max
  117. * to "min" and "max" and store them in "p".
  118. *
  119. * In particular, create a ppcg_macros object and attach it
  120. * as a note to the printer.
  121. */
  122. __isl_give isl_printer *ppcg_set_macros(__isl_take isl_printer *p,
  123. const char *min, const char *max)
  124. {
  125. isl_ctx *ctx;
  126. isl_id *id, *macros_id;
  127. struct ppcg_macros *macros;
  128. if (!p)
  129. return NULL;
  130. ctx = isl_printer_get_ctx(p);
  131. macros = isl_alloc_type(ctx, struct ppcg_macros);
  132. if (!macros)
  133. return isl_printer_free(p);
  134. macros->min = min;
  135. macros->max = max;
  136. id = isl_id_alloc(ctx, ppcg_macros, NULL);
  137. macros_id = isl_id_alloc(ctx, NULL, macros);
  138. if (!macros_id)
  139. ppcg_macros_free(macros);
  140. else
  141. macros_id = isl_id_set_free_user(macros_id, &ppcg_macros_free);
  142. p = isl_printer_set_note(p, id, macros_id);
  143. return p;
  144. }
  145. /* Return the ppcg_macros object that holds the currently active
  146. * macro definitions in "p".
  147. * If "p" has a note with macro definitions, then return those.
  148. * Otherwise, return the default macro definitions.
  149. */
  150. static struct ppcg_macros *get_macros(__isl_keep isl_printer *p)
  151. {
  152. isl_id *id;
  153. isl_bool has_macros;
  154. struct ppcg_macros *macros;
  155. id = isl_id_alloc(isl_printer_get_ctx(p), ppcg_macros, NULL);
  156. has_macros = isl_printer_has_note(p, id);
  157. if (has_macros < 0 || !has_macros) {
  158. isl_id_free(id);
  159. if (has_macros < 0)
  160. return NULL;
  161. return &ppcg_macros_default;
  162. }
  163. id = isl_printer_get_note(p, id);
  164. macros = isl_id_get_user(id);
  165. isl_id_free(id);
  166. return macros;
  167. }
  168. /* Print the currently active macro definition for ppcg_max.
  169. */
  170. static __isl_give isl_printer *print_max(__isl_take isl_printer *p)
  171. {
  172. struct ppcg_macros *macros;
  173. macros = get_macros(p);
  174. if (!macros)
  175. return isl_printer_free(p);
  176. return print_ppcg_macro(p, ppcg_max, macros->max, ppcg_max_printed);
  177. }
  178. /* Print the currently active macro definition for ppcg_min.
  179. */
  180. static __isl_give isl_printer *print_min(__isl_take isl_printer *p)
  181. {
  182. struct ppcg_macros *macros;
  183. macros = get_macros(p);
  184. if (!macros)
  185. return isl_printer_free(p);
  186. return print_ppcg_macro(p, ppcg_min, macros->min, ppcg_min_printed);
  187. }
  188. /* Print a macro definition for "type" to "p".
  189. * If GNU extensions are allowed, then print a specialized definition
  190. * for isl_ast_op_min and isl_ast_op_max.
  191. * Otherwise, use the default isl definition.
  192. */
  193. __isl_give isl_printer *ppcg_print_macro(enum isl_ast_op_type type,
  194. __isl_take isl_printer *p)
  195. {
  196. isl_ctx *ctx;
  197. struct ppcg_options *options;
  198. if (!p)
  199. return NULL;
  200. ctx = isl_printer_get_ctx(p);
  201. options = isl_ctx_peek_options(ctx, &ppcg_options_args);
  202. if (!options || !options->allow_gnu_extensions)
  203. return isl_ast_op_type_print_macro(type, p);
  204. switch (type) {
  205. case isl_ast_op_max:
  206. return print_max(p);
  207. case isl_ast_op_min:
  208. return print_min(p);
  209. default:
  210. return isl_ast_op_type_print_macro(type, p);
  211. }
  212. }
  213. /* isl_ast_expr_foreach_ast_op_type or isl_ast_node_foreach_ast_op_type
  214. * callback that prints a macro definition for "type".
  215. */
  216. static isl_stat print_macro(enum isl_ast_op_type type, void *user)
  217. {
  218. isl_printer **p = user;
  219. *p = ppcg_print_macro(type, *p);
  220. if (!*p)
  221. return isl_stat_error;
  222. return isl_stat_ok;
  223. }
  224. /* Print the required macros for "expr".
  225. */
  226. __isl_give isl_printer *ppcg_ast_expr_print_macros(
  227. __isl_keep isl_ast_expr *expr, __isl_take isl_printer *p)
  228. {
  229. if (isl_ast_expr_foreach_ast_op_type(expr, &print_macro, &p) < 0)
  230. return isl_printer_free(p);
  231. return p;
  232. }
  233. /* isl_id_to_ast_expr_foreach callback that prints the required
  234. * macro definitions for "val".
  235. */
  236. static isl_stat print_expr_macros(__isl_take isl_id *key,
  237. __isl_take isl_ast_expr *val, void *user)
  238. {
  239. isl_printer **p = user;
  240. *p = ppcg_ast_expr_print_macros(val, *p);
  241. isl_id_free(key);
  242. isl_ast_expr_free(val);
  243. if (!*p)
  244. return isl_stat_error;
  245. return isl_stat_ok;
  246. }
  247. /* Print the required macro definitions for the body of a statement in which
  248. * the access expressions are replaced by the isl_ast_expr objects
  249. * in "ref2expr".
  250. */
  251. __isl_give isl_printer *ppcg_print_body_macros(__isl_take isl_printer *p,
  252. __isl_keep isl_id_to_ast_expr *ref2expr)
  253. {
  254. if (isl_id_to_ast_expr_foreach(ref2expr, &print_expr_macros, &p) < 0)
  255. return isl_printer_free(p);
  256. return p;
  257. }
  258. /* Print the required macros for "node".
  259. */
  260. __isl_give isl_printer *ppcg_print_macros(__isl_take isl_printer *p,
  261. __isl_keep isl_ast_node *node)
  262. {
  263. if (isl_ast_node_foreach_ast_op_type(node, &print_macro, &p) < 0)
  264. return isl_printer_free(p);
  265. return p;
  266. }
  267. /* Names used for the macros that may appear in a printed isl AST.
  268. */
  269. const char *ppcg_min = "ppcg_min";
  270. const char *ppcg_max = "ppcg_max";
  271. const char *ppcg_fdiv_q = "ppcg_fdiv_q";
  272. /* Set the names of the macros that may appear in a printed isl AST.
  273. */
  274. __isl_give isl_printer *ppcg_set_macro_names(__isl_take isl_printer *p)
  275. {
  276. p = isl_ast_op_type_set_print_name(p, isl_ast_op_min, ppcg_min);
  277. p = isl_ast_op_type_set_print_name(p, isl_ast_op_max, ppcg_max);
  278. p = isl_ast_op_type_set_print_name(p, isl_ast_op_fdiv_q, ppcg_fdiv_q);
  279. return p;
  280. }
  281. /* Given a multi affine expression "mpa" without domain, modify it to have
  282. * the schedule space of "build" as domain.
  283. *
  284. * If the schedule space of "build" is a parameter space, then nothing
  285. * needs to be done.
  286. * Otherwise, "mpa" is first given a 0D domain and then it is combined
  287. * with a mapping from the schedule space of "build" to the same 0D domain.
  288. */
  289. __isl_give isl_multi_pw_aff *ppcg_attach_multi_pw_aff(
  290. __isl_take isl_multi_pw_aff *mpa, __isl_keep isl_ast_build *build)
  291. {
  292. isl_bool params;
  293. isl_space *space;
  294. isl_multi_aff *ma;
  295. space = isl_ast_build_get_schedule_space(build);
  296. params = isl_space_is_params(space);
  297. if (params < 0 || params) {
  298. isl_space_free(space);
  299. if (params < 0)
  300. return isl_multi_pw_aff_free(mpa);
  301. return mpa;
  302. }
  303. space = isl_space_from_domain(space);
  304. ma = isl_multi_aff_zero(space);
  305. mpa = isl_multi_pw_aff_from_range(mpa);
  306. mpa = isl_multi_pw_aff_pullback_multi_aff(mpa, ma);
  307. return mpa;
  308. }
  309. /* Build an access AST expression from "size" using "build".
  310. * "size" does not have a domain, but "build" may have a proper schedule space.
  311. * First modify "size" to have that schedule space as domain.
  312. */
  313. __isl_give isl_ast_expr *ppcg_build_size_expr(__isl_take isl_multi_pw_aff *size,
  314. __isl_keep isl_ast_build *build)
  315. {
  316. size = ppcg_attach_multi_pw_aff(size, build);
  317. return isl_ast_build_access_from_multi_pw_aff(build, size);
  318. }
  319. /* Print a declaration for an array with element type "base_type" and
  320. * size "size" to "p".
  321. */
  322. __isl_give isl_printer *ppcg_print_declaration_with_size(
  323. __isl_take isl_printer *p, const char *base_type,
  324. __isl_keep isl_ast_expr *size)
  325. {
  326. if (!base_type || !size)
  327. return isl_printer_free(p);
  328. p = ppcg_ast_expr_print_macros(size, p);
  329. p = isl_printer_start_line(p);
  330. p = isl_printer_print_str(p, base_type);
  331. p = isl_printer_print_str(p, " ");
  332. p = isl_printer_print_ast_expr(p, size);
  333. p = isl_printer_print_str(p, ";");
  334. p = isl_printer_end_line(p);
  335. return p;
  336. }
  337. /* Print a declaration for array "array" to "p", using "build"
  338. * to simplify any size expressions.
  339. *
  340. * The size is computed from the extent of the array and is
  341. * subsequently converted to an "access expression" by "build".
  342. */
  343. __isl_give isl_printer *ppcg_print_declaration(__isl_take isl_printer *p,
  344. struct pet_array *array, __isl_keep isl_ast_build *build)
  345. {
  346. isl_multi_pw_aff *size;
  347. isl_ast_expr *expr;
  348. if (!array)
  349. return isl_printer_free(p);
  350. size = ppcg_size_from_extent(isl_set_copy(array->extent));
  351. expr = isl_ast_build_access_from_multi_pw_aff(build, size);
  352. p = ppcg_print_declaration_with_size(p, array->element_type, expr);
  353. isl_ast_expr_free(expr);
  354. return p;
  355. }
  356. /* Print declarations for the arrays in "scop" that are declared
  357. * and that are exposed (if exposed == 1) or not exposed (if exposed == 0).
  358. */
  359. static __isl_give isl_printer *print_declarations(__isl_take isl_printer *p,
  360. struct ppcg_scop *scop, int exposed)
  361. {
  362. int i;
  363. isl_ast_build *build;
  364. if (!scop)
  365. return isl_printer_free(p);
  366. build = isl_ast_build_from_context(isl_set_copy(scop->context));
  367. for (i = 0; i < scop->pet->n_array; ++i) {
  368. struct pet_array *array = scop->pet->arrays[i];
  369. if (!array->declared)
  370. continue;
  371. if (array->exposed != exposed)
  372. continue;
  373. p = ppcg_print_declaration(p, array, build);
  374. }
  375. isl_ast_build_free(build);
  376. return p;
  377. }
  378. /* Print declarations for the arrays in "scop" that are declared
  379. * and exposed to the code after the scop.
  380. */
  381. __isl_give isl_printer *ppcg_print_exposed_declarations(
  382. __isl_take isl_printer *p, struct ppcg_scop *scop)
  383. {
  384. return print_declarations(p, scop, 1);
  385. }
  386. /* Print declarations for the arrays in "scop" that are declared,
  387. * but not exposed to the code after the scop.
  388. */
  389. __isl_give isl_printer *ppcg_print_hidden_declarations(
  390. __isl_take isl_printer *p, struct ppcg_scop *scop)
  391. {
  392. return print_declarations(p, scop, 0);
  393. }