polybench_test.sh.in: define POLYBENCH_USE_C99_PROTO
[ppcg.git] / gpu_print.c
blob4bcf75740c92093f5f03f102c6eaf16ab4a6151c
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 <isl/aff.h>
12 #include "gpu_print.h"
13 #include "pet_printer.h"
14 #include "schedule.h"
16 static int print_macro(enum isl_ast_op_type type, void *user)
18 isl_printer **p = user;
20 if (type == isl_ast_op_fdiv_q)
21 return 0;
23 *p = isl_ast_op_type_print_macro(type, *p);
25 return 0;
28 /* Print the required macros for "node", including one for floord.
29 * We always print a macro for floord as it may also appear in the statements.
31 __isl_give isl_printer *gpu_print_macros(__isl_take isl_printer *p,
32 __isl_keep isl_ast_node *node)
34 p = isl_ast_op_type_print_macro(isl_ast_op_fdiv_q, p);
35 if (isl_ast_node_foreach_ast_op_type(node, &print_macro, &p) < 0)
36 return isl_printer_free(p);
37 return p;
40 /* Print an expression for the size of "array" in bytes.
42 __isl_give isl_printer *gpu_array_info_print_size(__isl_take isl_printer *prn,
43 struct gpu_array_info *array)
45 int i;
47 for (i = 0; i < array->n_index; ++i) {
48 prn = isl_printer_print_str(prn, "(");
49 prn = isl_printer_print_pw_aff(prn, array->bound[i]);
50 prn = isl_printer_print_str(prn, ") * ");
52 prn = isl_printer_print_str(prn, "sizeof(");
53 prn = isl_printer_print_str(prn, array->type);
54 prn = isl_printer_print_str(prn, ")");
56 return prn;
59 /* Print an access to the element in the private/shared memory copy
60 * described by "stmt". The index of the copy is recorded in
61 * stmt->local_index as a "call" to the array.
63 static __isl_give isl_printer *stmt_print_local_index(__isl_take isl_printer *p,
64 struct ppcg_kernel_stmt *stmt)
66 int i;
67 isl_ast_expr *expr;
68 struct gpu_array_info *array = stmt->u.c.array;
70 expr = isl_ast_expr_get_op_arg(stmt->u.c.local_index, 0);
71 p = isl_printer_print_ast_expr(p, expr);
72 isl_ast_expr_free(expr);
74 for (i = 0; i < array->n_index; ++i) {
75 expr = isl_ast_expr_get_op_arg(stmt->u.c.local_index, 1 + i);
77 p = isl_printer_print_str(p, "[");
78 p = isl_printer_print_ast_expr(p, expr);
79 p = isl_printer_print_str(p, "]");
81 isl_ast_expr_free(expr);
84 return p;
87 /* Print an access to the element in the global memory copy
88 * described by "stmt". The index of the copy is recorded in
89 * stmt->index as a "call" to the array.
91 * The copy in global memory has been linearized, so we need to take
92 * the array size into account.
94 static __isl_give isl_printer *stmt_print_global_index(
95 __isl_take isl_printer *p, struct ppcg_kernel_stmt *stmt)
97 int i;
98 struct gpu_array_info *array = stmt->u.c.array;
99 isl_pw_aff_list *bound = stmt->u.c.local_array->bound;
101 if (gpu_array_is_scalar(array)) {
102 if (!array->read_only)
103 p = isl_printer_print_str(p, "*");
104 p = isl_printer_print_str(p, array->name);
105 return p;
108 p = isl_printer_print_str(p, array->name);
109 p = isl_printer_print_str(p, "[");
110 for (i = 0; i + 1 < array->n_index; ++i)
111 p = isl_printer_print_str(p, "(");
112 for (i = 0; i < array->n_index; ++i) {
113 isl_ast_expr *expr;
114 expr = isl_ast_expr_get_op_arg(stmt->u.c.index, 1 + i);
115 if (i) {
116 isl_pw_aff *bound_i;
117 bound_i = isl_pw_aff_list_get_pw_aff(bound, i);
118 p = isl_printer_print_str(p, ") * (");
119 p = isl_printer_print_pw_aff(p, bound_i);
120 p = isl_printer_print_str(p, ") + (");
121 isl_pw_aff_free(bound_i);
123 p = isl_printer_print_ast_expr(p, expr);
124 if (i)
125 p = isl_printer_print_str(p, ")");
126 isl_ast_expr_free(expr);
128 p = isl_printer_print_str(p, "]");
130 return p;
133 /* Print a copy statement.
135 * A read copy statement is printed as
137 * local = global;
139 * while a write copy statement is printed as
141 * global = local;
143 __isl_give isl_printer *ppcg_kernel_print_copy(__isl_take isl_printer *p,
144 struct ppcg_kernel_stmt *stmt)
146 p = isl_printer_start_line(p);
147 if (stmt->u.c.read) {
148 p = stmt_print_local_index(p, stmt);
149 p = isl_printer_print_str(p, " = ");
150 p = stmt_print_global_index(p, stmt);
151 } else {
152 p = stmt_print_global_index(p, stmt);
153 p = isl_printer_print_str(p, " = ");
154 p = stmt_print_local_index(p, stmt);
156 p = isl_printer_print_str(p, ";");
157 p = isl_printer_end_line(p);
159 return p;
162 /* Print an access based on the information in "access".
163 * If this an access to global memory, then the index expression
164 * is linearized.
166 * If access->array is NULL, then we are
167 * accessing an iterator in the original program.
169 static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
170 struct ppcg_kernel_access *access)
172 int i;
173 unsigned n_index;
174 struct gpu_array_info *array;
175 isl_pw_aff_list *bound;
177 array = access->array;
178 bound = array ? access->local_array->bound : NULL;
179 if (!array)
180 p = isl_printer_print_str(p, "(");
181 else {
182 if (access->type == ppcg_access_global &&
183 gpu_array_is_scalar(array) && !array->read_only)
184 p = isl_printer_print_str(p, "*");
185 p = isl_printer_print_str(p, access->local_name);
186 if (gpu_array_is_scalar(array))
187 return p;
188 p = isl_printer_print_str(p, "[");
191 n_index = isl_ast_expr_list_n_ast_expr(access->index);
192 if (access->type == ppcg_access_global)
193 for (i = 0; i + 1 < n_index; ++i)
194 p = isl_printer_print_str(p, "(");
196 for (i = 0; i < n_index; ++i) {
197 isl_ast_expr *index;
199 index = isl_ast_expr_list_get_ast_expr(access->index, i);
200 if (array && i) {
201 if (access->type == ppcg_access_global) {
202 isl_pw_aff *bound_i;
203 bound_i = isl_pw_aff_list_get_pw_aff(bound, i);
204 p = isl_printer_print_str(p, ") * (");
205 p = isl_printer_print_pw_aff(p, bound_i);
206 p = isl_printer_print_str(p, ") + ");
207 isl_pw_aff_free(bound_i);
208 } else
209 p = isl_printer_print_str(p, "][");
211 p = isl_printer_print_ast_expr(p, index);
212 isl_ast_expr_free(index);
214 if (!array)
215 p = isl_printer_print_str(p, ")");
216 else
217 p = isl_printer_print_str(p, "]");
219 return p;
222 struct gpu_access_print_info {
223 int i;
224 struct ppcg_kernel_stmt *stmt;
227 /* To print the gpu accesses we walk the list of gpu accesses simultaneously
228 * with the pet printer. This means that whenever the pet printer prints a
229 * pet access expression we have the corresponding gpu access available and can
230 * print the modified access.
232 static __isl_give isl_printer *print_gpu_access(__isl_take isl_printer *p,
233 struct pet_expr *expr, void *usr)
235 struct gpu_access_print_info *info =
236 (struct gpu_access_print_info *) usr;
238 p = print_access(p, &info->stmt->u.d.access[info->i]);
239 info->i++;
241 return p;
244 __isl_give isl_printer *ppcg_kernel_print_domain(__isl_take isl_printer *p,
245 struct ppcg_kernel_stmt *stmt)
247 struct gpu_access_print_info info;
249 info.i = 0;
250 info.stmt = stmt;
252 p = isl_printer_start_line(p);
253 p = print_pet_expr(p, stmt->u.d.stmt->body, &print_gpu_access, &info);
254 p = isl_printer_print_str(p, ";");
255 p = isl_printer_end_line(p);
257 return p;