construct shared memory copying statements inline
[ppcg.git] / gpucode.c
blob9460941fb02b9c774ba572fda492c5c575570c9a
1 /*
2 * Copyright 2010-2011 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
11 #include "gpucode.h"
13 void print_cloog_macros(FILE *dst)
15 fprintf(dst,
16 "#define floord(n,d) (((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))\n");
17 fprintf(dst,
18 "#define ceild(n,d) (((n)<0) ? -((-(n))/(d)) : ((n)+(d)-1)/(d))\n");
19 fprintf(dst, "#define max(x,y) ((x) > (y) ? (x) : (y))\n");
20 fprintf(dst, "#define min(x,y) ((x) < (y) ? (x) : (y))\n");
23 static void print_expr(struct clast_expr *e, FILE *dst);
24 static void print_stmt(struct gpucode_info *info, struct clast_stmt *s);
26 void print_indent(FILE *dst, int indent)
28 fprintf(dst, "%*s", indent, "");
31 static void print_name(struct clast_name *n, FILE *dst)
33 fprintf(dst, "%s", n->name);
36 static void print_term(struct clast_term *t, FILE *dst)
38 if (!t->var) {
39 cloog_int_print(dst, t->val);
40 } else {
41 if (!cloog_int_is_one(t->val)) {
42 cloog_int_print(dst, t->val);
43 fprintf(dst, "*");
45 if (t->var->type == clast_expr_red)
46 fprintf(dst, "(");
47 print_expr(t->var, dst);
48 if (t->var->type == clast_expr_red)
49 fprintf(dst, ")");
53 static void print_bin(struct clast_binary *b, FILE *dst)
55 const char *s1, *s2, *s3;
56 switch (b->type) {
57 case clast_bin_mod:
58 s1 = "(", s2 = ")%", s3 = "";
59 break;
60 case clast_bin_div:
61 s1 = "(", s2 = ")/(", s3 = ")";
62 break;
63 case clast_bin_cdiv:
64 s1 = "ceild(", s2 = ", ", s3 = ")";
65 break;
66 case clast_bin_fdiv:
67 s1 = "floord(", s2 = ", ", s3 = ")";
68 break;
69 default:
70 assert(0);
72 fprintf(dst, "%s", s1);
73 print_expr(b->LHS, dst);
74 fprintf(dst, "%s", s2);
75 cloog_int_print(dst, b->RHS);
76 fprintf(dst, "%s", s3);
79 static void print_red(struct clast_reduction *r, FILE *dst)
81 int i;
82 const char *s1, *s2, *s3;
84 if (r->n == 1) {
85 print_expr(r->elts[0], dst);
86 return;
89 switch (r->type) {
90 case clast_red_sum:
91 s1 = "", s2 = " + ", s3 = "";
92 break;
93 case clast_red_max:
94 s1 = "max(", s2 = ", ", s3 = ")";
95 break;
96 case clast_red_min:
97 s1 = "min(", s2 = ", ", s3 = ")";
98 break;
99 default:
100 assert(0);
103 for (i = 1; i < r->n; ++i)
104 fprintf(dst, "%s", s1);
105 print_expr(r->elts[0], dst);
106 for (i = 1; i < r->n; ++i) {
107 if (r->type == clast_red_sum && r->elts[i]->type == clast_expr_term &&
108 cloog_int_is_neg(((struct clast_term *) r->elts[i])->val)) {
109 struct clast_term *t = (struct clast_term *) r->elts[i];
110 cloog_int_neg(t->val, t->val);
111 fprintf(dst, " - ");
112 print_expr(r->elts[i], dst);
113 cloog_int_neg(t->val, t->val);
114 } else {
115 fprintf(dst, "%s", s2);
116 print_expr(r->elts[i], dst);
118 fprintf(dst, "%s", s3);
122 static void print_expr(struct clast_expr *e, FILE *dst)
124 switch (e->type) {
125 case clast_expr_name:
126 print_name((struct clast_name*) e, dst);
127 break;
128 case clast_expr_term:
129 print_term((struct clast_term*) e, dst);
130 break;
131 case clast_expr_red:
132 print_red((struct clast_reduction*) e, dst);
133 break;
134 case clast_expr_bin:
135 print_bin((struct clast_binary*) e, dst);
136 break;
137 default:
138 assert(0);
142 static void print_ass(struct clast_assignment *a, FILE *dst, int indent,
143 int first_ass)
145 print_indent(dst, indent);
146 if (first_ass)
147 fprintf(dst, "int ");
148 fprintf(dst, "%s = ", a->LHS);
149 print_expr(a->RHS, dst);
150 fprintf(dst, ";\n");
153 static void print_guard(struct gpucode_info *info, struct clast_guard *g)
155 int i;
156 int n = g->n;
158 print_indent(info->dst, info->indent);
159 fprintf(info->dst, "if (");
160 for (i = 0; i < n; ++i) {
161 if (i > 0)
162 fprintf(info->dst," && ");
163 if (n > 1)
164 fprintf(info->dst,"(");
165 print_expr(g->eq[i].LHS, info->dst);
166 if (g->eq[i].sign == 0)
167 fprintf(info->dst," == ");
168 else if (g->eq[i].sign > 0)
169 fprintf(info->dst," >= ");
170 else
171 fprintf(info->dst," <= ");
172 print_expr(g->eq[i].RHS, info->dst);
173 if (n > 1)
174 fprintf(info->dst,")");
176 fprintf(info->dst, ") {\n");
177 info->indent += 4;
178 print_stmt(info, g->then);
179 info->indent -= 4;
180 print_indent(info->dst, info->indent);
181 fprintf(info->dst, "}\n");
184 static void print_for(struct gpucode_info *info, struct clast_for *f)
186 assert(f->LB && f->UB);
187 print_indent(info->dst, info->indent);
188 fprintf(info->dst, "for (int %s = ", f->iterator);
189 print_expr(f->LB, info->dst);
190 fprintf(info->dst, "; %s <= ", f->iterator);
191 print_expr(f->UB, info->dst);
192 fprintf(info->dst, "; %s", f->iterator);
193 if (cloog_int_is_one(f->stride))
194 fprintf(info->dst, "++");
195 else {
196 fprintf(info->dst, " += ");
197 cloog_int_print(info->dst, f->stride);
199 fprintf(info->dst, ") {\n");
200 info->indent += 4;
201 if (info->print_for_head)
202 info->print_for_head(info, f);
203 print_stmt(info, f->body);
204 if (info->print_for_foot)
205 info->print_for_foot(info, f);
206 info->indent -= 4;
207 print_indent(info->dst, info->indent);
208 fprintf(info->dst, "}\n");
211 static void print_user_stmt(struct clast_user_stmt *u, FILE *dst, int indent)
213 struct clast_stmt *t;
215 print_indent(dst, indent);
216 fprintf(dst, "%s", u->statement->name);
217 fprintf(dst, "(");
218 for (t = u->substitutions; t; t = t->next) {
219 assert(CLAST_STMT_IS_A(t, stmt_ass));
220 print_expr(((struct clast_assignment *) t)->RHS, dst);
221 if (t->next)
222 fprintf(dst, ",");
224 fprintf(dst, ");\n");
227 static void print_stmt(struct gpucode_info *info, struct clast_stmt *s)
229 int first_ass = 1;
231 for ( ; s; s = s->next) {
232 if (CLAST_STMT_IS_A(s, stmt_root))
233 continue;
234 if (CLAST_STMT_IS_A(s, stmt_ass)) {
235 print_ass((struct clast_assignment *) s, info->dst, info->indent,
236 first_ass);
237 first_ass = 0;
238 } else if (CLAST_STMT_IS_A(s, stmt_user)) {
239 if (info->print_user_stmt_list) {
240 info->print_user_stmt_list(info, (struct clast_user_stmt *) s);
241 return;
242 } else if (info->print_user_stmt)
243 info->print_user_stmt(info, (struct clast_user_stmt *) s);
244 else
245 print_user_stmt((struct clast_user_stmt *) s, info->dst,
246 info->indent);
247 } else if (CLAST_STMT_IS_A(s, stmt_for)) {
248 print_for(info, (struct clast_for *) s);
249 } else if (CLAST_STMT_IS_A(s, stmt_guard)) {
250 print_guard(info, (struct clast_guard *) s);
251 } else {
252 assert(0);
257 void gpu_print_host_stmt(struct gpucode_info *info, struct clast_stmt *s)
259 print_stmt(info, s);
262 __isl_give isl_set *extract_host_domain(struct clast_user_stmt *u)
264 return isl_set_from_cloog_domain(cloog_domain_copy(u->domain));
267 /* Extract the set of scattering dimension values for which the given
268 * sequence of user statements is executed.
269 * In principle, this set should be the same for each of the user
270 * statements in the sequence, but we compute the union just to be safe.
272 __isl_give isl_set *extract_entire_host_domain(struct clast_user_stmt *u)
274 struct clast_stmt *s;
275 isl_set *host_domain = NULL;
277 for (s = &u->stmt; s; s = s->next) {
278 isl_set *set_i;
280 assert(CLAST_STMT_IS_A(s, stmt_user));
281 u = (struct clast_user_stmt *) s;
283 set_i = extract_host_domain(u);
285 if (!host_domain)
286 host_domain = set_i;
287 else
288 host_domain = isl_set_union(host_domain, set_i);
289 assert(host_domain);
292 return isl_set_coalesce(host_domain);