gpu backend: declare local variables that are used on the host
[ppcg.git] / gpu_print.c
bloba53f7ad1f0b5b9dffa7346d1a92073c87e4393b7
1 /*
2 * Copyright 2012 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 <string.h>
12 #include <isl/aff.h>
14 #include "gpu_print.h"
15 #include "print.h"
16 #include "schedule.h"
18 /* Print declarations to "p" for arrays that are local to "prog"
19 * but that are used on the host and therefore require a declaration.
21 __isl_give isl_printer *gpu_print_local_declarations(__isl_take isl_printer *p,
22 struct gpu_prog *prog)
24 int i;
26 if (!prog)
27 return isl_printer_free(p);
29 for (i = 0; i < prog->n_array; ++i) {
30 if (!prog->array[i].declare_local)
31 continue;
32 p = ppcg_print_declaration(p, prog->scop->pet->arrays[i]);
35 return p;
38 static int print_macro(enum isl_ast_op_type type, void *user)
40 isl_printer **p = user;
42 if (type == isl_ast_op_fdiv_q)
43 return 0;
45 *p = isl_ast_op_type_print_macro(type, *p);
47 return 0;
50 /* Print the required macros for "node", including one for floord.
51 * We always print a macro for floord as it may also appear in the statements.
53 __isl_give isl_printer *gpu_print_macros(__isl_take isl_printer *p,
54 __isl_keep isl_ast_node *node)
56 p = isl_ast_op_type_print_macro(isl_ast_op_fdiv_q, p);
57 if (isl_ast_node_foreach_ast_op_type(node, &print_macro, &p) < 0)
58 return isl_printer_free(p);
59 return p;
62 /* Print an expression for the size of "array" in bytes.
64 __isl_give isl_printer *gpu_array_info_print_size(__isl_take isl_printer *prn,
65 struct gpu_array_info *array)
67 int i;
69 for (i = 0; i < array->n_index; ++i) {
70 prn = isl_printer_print_str(prn, "(");
71 prn = isl_printer_print_pw_aff(prn, array->bound[i]);
72 prn = isl_printer_print_str(prn, ") * ");
74 prn = isl_printer_print_str(prn, "sizeof(");
75 prn = isl_printer_print_str(prn, array->type);
76 prn = isl_printer_print_str(prn, ")");
78 return prn;
81 /* Print the declaration of a non-linearized array argument.
83 static __isl_give isl_printer *print_non_linearized_declaration_argument(
84 __isl_take isl_printer *p, struct gpu_array_info *array)
86 int i;
88 p = isl_printer_print_str(p, array->type);
89 p = isl_printer_print_str(p, " ");
91 p = isl_printer_print_str(p, array->name);
93 for (i = 0; i < array->n_index; i++) {
94 p = isl_printer_print_str(p, "[");
95 p = isl_printer_print_pw_aff(p, array->bound[i]);
96 p = isl_printer_print_str(p, "]");
99 return p;
102 /* Print the declaration of an array argument.
103 * "memory_space" allows to specify a memory space prefix.
105 __isl_give isl_printer *gpu_array_info_print_declaration_argument(
106 __isl_take isl_printer *p, struct gpu_array_info *array,
107 const char *memory_space)
109 if (gpu_array_is_read_only_scalar(array)) {
110 p = isl_printer_print_str(p, array->type);
111 p = isl_printer_print_str(p, " ");
112 p = isl_printer_print_str(p, array->name);
113 return p;
116 if (memory_space) {
117 p = isl_printer_print_str(p, memory_space);
118 p = isl_printer_print_str(p, " ");
121 if (array->n_index != 0 && !array->linearize)
122 return print_non_linearized_declaration_argument(p, array);
124 p = isl_printer_print_str(p, array->type);
125 p = isl_printer_print_str(p, " ");
126 p = isl_printer_print_str(p, "*");
127 p = isl_printer_print_str(p, array->name);
129 return p;
132 /* Print the call of an array argument.
134 __isl_give isl_printer *gpu_array_info_print_call_argument(
135 __isl_take isl_printer *p, struct gpu_array_info *array)
137 if (gpu_array_is_read_only_scalar(array))
138 return isl_printer_print_str(p, array->name);
140 p = isl_printer_print_str(p, "dev_");
141 p = isl_printer_print_str(p, array->name);
143 return p;
146 /* Print an access to the element in the private/shared memory copy
147 * described by "stmt". The index of the copy is recorded in
148 * stmt->local_index as an access to the array.
150 static __isl_give isl_printer *stmt_print_local_index(__isl_take isl_printer *p,
151 struct ppcg_kernel_stmt *stmt)
153 return isl_printer_print_ast_expr(p, stmt->u.c.local_index);
156 /* Print an access to the element in the global memory copy
157 * described by "stmt". The index of the copy is recorded in
158 * stmt->index as an access to the array.
160 * The copy in global memory has been linearized, so we need to take
161 * the array size into account.
163 static __isl_give isl_printer *stmt_print_global_index(
164 __isl_take isl_printer *p, struct ppcg_kernel_stmt *stmt)
166 int i;
167 struct gpu_array_info *array = stmt->u.c.array;
168 struct gpu_local_array_info *local = stmt->u.c.local_array;
169 isl_ast_expr *index;
171 if (gpu_array_is_scalar(array)) {
172 if (!gpu_array_is_read_only_scalar(array))
173 p = isl_printer_print_str(p, "*");
174 p = isl_printer_print_str(p, array->name);
175 return p;
178 index = isl_ast_expr_copy(stmt->u.c.index);
179 if (array->linearize)
180 index = gpu_local_array_info_linearize_index(local, index);
182 p = isl_printer_print_ast_expr(p, index);
183 isl_ast_expr_free(index);
185 return p;
188 /* Print a copy statement.
190 * A read copy statement is printed as
192 * local = global;
194 * while a write copy statement is printed as
196 * global = local;
198 __isl_give isl_printer *ppcg_kernel_print_copy(__isl_take isl_printer *p,
199 struct ppcg_kernel_stmt *stmt)
201 p = isl_printer_start_line(p);
202 if (stmt->u.c.read) {
203 p = stmt_print_local_index(p, stmt);
204 p = isl_printer_print_str(p, " = ");
205 p = stmt_print_global_index(p, stmt);
206 } else {
207 p = stmt_print_global_index(p, stmt);
208 p = isl_printer_print_str(p, " = ");
209 p = stmt_print_local_index(p, stmt);
211 p = isl_printer_print_str(p, ";");
212 p = isl_printer_end_line(p);
214 return p;
217 __isl_give isl_printer *ppcg_kernel_print_domain(__isl_take isl_printer *p,
218 struct ppcg_kernel_stmt *stmt)
220 return pet_stmt_print_body(stmt->u.d.stmt->stmt, p, stmt->u.d.ref2expr);
223 /* Was the definition of "type" printed before?
224 * That is, does its name appear in the list of printed types "types"?
226 static int already_printed(struct gpu_types *types,
227 struct pet_type *type)
229 int i;
231 for (i = 0; i < types->n; ++i)
232 if (!strcmp(types->name[i], type->name))
233 return 1;
235 return 0;
238 /* Print the definitions of all types prog->scop that have not been
239 * printed before (according to "types") on "p".
240 * Extend the list of printed types "types" with the newly printed types.
242 __isl_give isl_printer *gpu_print_types(__isl_take isl_printer *p,
243 struct gpu_types *types, struct gpu_prog *prog)
245 int i, n;
246 isl_ctx *ctx;
247 char **name;
249 n = prog->scop->pet->n_type;
251 if (n == 0)
252 return p;
254 ctx = isl_printer_get_ctx(p);
255 name = isl_realloc_array(ctx, types->name, char *, types->n + n);
256 if (!name)
257 return isl_printer_free(p);
258 types->name = name;
260 for (i = 0; i < n; ++i) {
261 struct pet_type *type = prog->scop->pet->types[i];
263 if (already_printed(types, type))
264 continue;
266 p = isl_printer_start_line(p);
267 p = isl_printer_print_str(p, type->definition);
268 p = isl_printer_print_str(p, ";");
269 p = isl_printer_end_line(p);
271 types->name[types->n++] = strdup(type->name);
274 return p;