initial version of ppcg
[ppcg.git] / gpucode.c
blobac0d2d32979d90b318d49b730d29406676740de3
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 fprintf(info->dst,"(");
164 print_expr(g->eq[i].LHS, info->dst);
165 if (g->eq[i].sign == 0)
166 fprintf(info->dst," == ");
167 else if (g->eq[i].sign > 0)
168 fprintf(info->dst," >= ");
169 else
170 fprintf(info->dst," <= ");
171 print_expr(g->eq[i].RHS, info->dst);
172 fprintf(info->dst,")");
174 fprintf(info->dst, ") {\n");
175 info->indent += 4;
176 print_stmt(info, g->then);
177 info->indent -= 4;
178 print_indent(info->dst, info->indent);
179 fprintf(info->dst, "}\n");
182 static void print_for(struct gpucode_info *info, struct clast_for *f)
184 assert(f->LB && f->UB);
185 print_indent(info->dst, info->indent);
186 fprintf(info->dst, "for (int %s = ", f->iterator);
187 print_expr(f->LB, info->dst);
188 fprintf(info->dst, "; %s <= ", f->iterator);
189 print_expr(f->UB, info->dst);
190 fprintf(info->dst, "; %s", f->iterator);
191 if (cloog_int_is_one(f->stride))
192 fprintf(info->dst, "++");
193 else {
194 fprintf(info->dst, " += ");
195 cloog_int_print(info->dst, f->stride);
197 fprintf(info->dst, ") {\n");
198 info->indent += 4;
199 if (info->print_for_head)
200 info->print_for_head(info, f);
201 print_stmt(info, f->body);
202 if (info->print_for_foot)
203 info->print_for_foot(info, f);
204 info->indent -= 4;
205 print_indent(info->dst, info->indent);
206 fprintf(info->dst, "}\n");
209 static void print_user_stmt(struct clast_user_stmt *u, FILE *dst, int indent)
211 struct clast_stmt *t;
213 print_indent(dst, indent);
214 fprintf(dst, "%s", u->statement->name);
215 fprintf(dst, "(");
216 for (t = u->substitutions; t; t = t->next) {
217 assert(CLAST_STMT_IS_A(t, stmt_ass));
218 print_expr(((struct clast_assignment *) t)->RHS, dst);
219 if (t->next)
220 fprintf(dst, ",");
222 fprintf(dst, ");\n");
225 static void print_stmt(struct gpucode_info *info, struct clast_stmt *s)
227 int first_ass = 1;
229 for ( ; s; s = s->next) {
230 if (CLAST_STMT_IS_A(s, stmt_root))
231 continue;
232 if (CLAST_STMT_IS_A(s, stmt_ass)) {
233 print_ass((struct clast_assignment *) s, info->dst, info->indent,
234 first_ass);
235 first_ass = 0;
236 } else if (CLAST_STMT_IS_A(s, stmt_user)) {
237 if (info->print_user_stmt_list) {
238 info->print_user_stmt_list(info, (struct clast_user_stmt *) s);
239 return;
240 } else if (info->print_user_stmt)
241 info->print_user_stmt(info, (struct clast_user_stmt *) s);
242 else
243 print_user_stmt((struct clast_user_stmt *) s, info->dst,
244 info->indent);
245 } else if (CLAST_STMT_IS_A(s, stmt_for)) {
246 print_for(info, (struct clast_for *) s);
247 } else if (CLAST_STMT_IS_A(s, stmt_guard)) {
248 print_guard(info, (struct clast_guard *) s);
249 } else {
250 assert(0);
255 void gpu_print_host_stmt(struct gpucode_info *info, struct clast_stmt *s)
257 print_stmt(info, s);
260 __isl_give isl_set *extract_host_domain(struct clast_user_stmt *u)
262 return isl_set_from_cloog_domain(cloog_domain_copy(u->domain));
265 /* Extract the set of scattering dimension values for which the given
266 * sequence of user statements is executed.
267 * In principle, this set should be the same for each of the user
268 * statements in the sequence, but we compute the union just to be safe.
270 __isl_give isl_set *extract_entire_host_domain(struct clast_user_stmt *u)
272 struct clast_stmt *s;
273 isl_set *host_domain = NULL;
275 for (s = &u->stmt; s; s = s->next) {
276 isl_set *set_i;
278 assert(CLAST_STMT_IS_A(s, stmt_user));
279 u = (struct clast_user_stmt *) s;
281 set_i = extract_host_domain(u);
283 if (!host_domain)
284 host_domain = set_i;
285 else
286 host_domain = isl_set_union(host_domain, set_i);
287 assert(host_domain);
290 return isl_set_coalesce(host_domain);