cuda.c: compute_private_size: don't put read only scalars in registers
[ppcg.git] / cpu.c
blob87c9bec8eb7e04ce543a0814ef5de7516a7d26c4
1 /*
2 * Copyright 2012 INRIA Paris-Rocquencourt
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Tobias Grosser, INRIA Paris-Rocquencourt,
7 * Domaine de Voluceau, Rocquenqourt, B.P. 105,
8 * 78153 Le Chesnay Cedex France
9 */
11 #include <limits.h>
12 #include <stdio.h>
14 #include <cloog/cloog.h>
15 #include <cloog/isl/cloog.h>
16 #include <isl/aff.h>
17 #include <isl/ctx.h>
18 #include <isl/map.h>
19 #include <pet.h>
21 #include "clast_printer.h"
22 #include "cpu.h"
23 #include "pet_printer.h"
24 #include "rewrite.h"
26 /* Derive the output file name from the input file name.
27 * 'input' is the entire path of the input file. The output
28 * is the file name plus the additional extension.
30 * We will basically replace everything after the last point
31 * with '.ppcg.c'. This means file.c becomes file.ppcg.c
33 FILE *get_output_file(const char *input)
35 char name[PATH_MAX];
36 const char *base;
37 const char *ext;
38 const char ppcg_marker[] = ".ppcg";
39 int len;
41 base = strrchr(input, '/');
42 if (base)
43 base++;
44 else
45 base = input;
46 ext = strrchr(base, '.');
47 len = ext ? ext - base : strlen(base);
49 memcpy(name, base, len);
50 strcpy(name + len, ppcg_marker);
51 strcpy(name + len + sizeof(ppcg_marker) - 1, ext);
53 return fopen(name, "w");
56 /* Print a memory access 'access' to the printer 'p'.
58 * Given a map [a,b,c] -> {S[i,j] -> A[i,j+a]} we will print: A[i][j+a].
60 * In case the output dimensions is one dimensional and unnamed we assume this
61 * is not a memory access, but just an expression. This means the example
62 * [a,b,c] -> {S[i,j] -> [j+a]} will be printed as: j+a
64 * The code that is printed is C code and the variable parameter and input
65 * dimension names are derived from the isl_dim names.
67 static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
68 __isl_take isl_map *access)
70 int i;
71 const char *name;
72 unsigned n_index;
73 isl_pw_multi_aff *pma;
75 n_index = isl_map_dim(access, isl_dim_out);
76 name = isl_map_get_tuple_name(access, isl_dim_out);
77 pma = isl_pw_multi_aff_from_map(access);
78 pma = isl_pw_multi_aff_coalesce(pma);
80 if (name == NULL) {
81 isl_pw_aff *index;
82 index = isl_pw_multi_aff_get_pw_aff(pma, 0);
83 p = isl_printer_print_str(p, "(");
84 p = isl_printer_print_pw_aff(p, index);
85 p = isl_printer_print_str(p, ")");
86 isl_pw_aff_free(index);
87 isl_pw_multi_aff_free(pma);
88 return p;
91 p = isl_printer_print_str(p, name);
93 for (i = 0; i < n_index; ++i) {
94 isl_pw_aff *index;
96 index = isl_pw_multi_aff_get_pw_aff(pma, i);
98 p = isl_printer_print_str(p, "[");
99 p = isl_printer_print_pw_aff(p, index);
100 p = isl_printer_print_str(p, "]");
101 isl_pw_aff_free(index);
104 isl_pw_multi_aff_free(pma);
106 return p;
109 static __isl_give isl_printer *print_cpu_access(__isl_take isl_printer *p,
110 struct pet_expr *expr, void *usr)
112 isl_map *access = isl_map_copy(expr->acc.access);
114 return print_access(p, access);
117 static void print_stmt_body(FILE *out, struct pet_stmt *stmt)
119 isl_ctx *ctx = isl_set_get_ctx(stmt->domain);
120 isl_printer *p;
122 p = isl_printer_to_file(ctx, out);
123 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
124 p = print_pet_expr(p, stmt->body, &print_cpu_access, out);
125 isl_printer_free(p);
128 /* Create a CloogInput data structure that describes the 'scop'.
130 static CloogInput *cloog_input_from_scop(CloogState *state,
131 struct pet_scop *scop)
133 CloogDomain *cloog_context;
134 CloogUnionDomain *ud;
135 CloogInput *input;
136 isl_set *context;
137 isl_union_set *domain_set;
138 isl_union_map *schedule_map;
140 scop = pet_scop_align_params(scop);
142 context = isl_set_copy(scop->context);
143 domain_set = pet_scop_collect_domains(scop);
144 schedule_map = pet_scop_collect_schedule(scop);
145 schedule_map = isl_union_map_intersect_domain(schedule_map, domain_set);
147 ud = cloog_union_domain_from_isl_union_map(schedule_map);
149 cloog_context = cloog_domain_from_isl_set(context);
151 input = cloog_input_alloc(cloog_context, ud);
153 return input;
156 /* Print a #define macro for every statement in the 'scop'.
158 static void print_stmt_definitions(struct pet_scop *scop, FILE *output)
160 int i, j;
162 for (i = 0; i < scop->n_stmt; ++i) {
163 struct pet_stmt *stmt = scop->stmts[i];
164 const char *name = isl_set_get_tuple_name(stmt->domain);
166 fprintf(output, "#define %s(", name);
168 for (j = 0; j < isl_set_dim(stmt->domain, isl_dim_set); ++j) {
169 const char *name;
171 if (j)
172 fprintf(output, ", ");
174 name = isl_set_get_dim_name(stmt->domain, isl_dim_set, j);
175 fprintf(output, "%s", name);
178 fprintf(output, ") ");
180 print_stmt_body(output, stmt);
182 fprintf(output, "\n");
186 /* Code generate the scop 'scop' and print the corresponding C code to
187 * 'output'.
189 static void print_scop(isl_ctx *ctx, struct pet_scop *scop, FILE *output)
191 CloogState *state;
192 CloogOptions *options;
193 CloogInput *input;
194 struct clast_stmt *stmt;
195 struct clast_printer_info code;
197 state = cloog_isl_state_malloc(ctx);
199 options = cloog_options_malloc(state);
200 options->language = CLOOG_LANGUAGE_C;
201 options->otl = 1;
202 options->strides = 1;
204 input = cloog_input_from_scop(state, scop);
205 stmt = cloog_clast_create_from_input(input, options);
207 code.indent = 0;
208 code.dst = output;
209 code.print_user_stmt = NULL;
210 code.print_user_stmt_list = NULL;
211 code.print_for_head = NULL;
212 code.print_for_foot = NULL;
214 print_cloog_macros(output);
215 fprintf(output, "\n");
216 print_stmt_definitions(scop, output);
217 fprintf(output, "\n");
218 print_clast(&code, stmt);
220 cloog_clast_free(stmt);
221 cloog_options_free(options);
222 cloog_state_free(state);
224 fprintf(output, "\n");
227 int generate_cpu(isl_ctx *ctx, struct pet_scop *scop,
228 struct ppcg_options *options, const char *input)
230 FILE *input_file;
231 FILE *output_file;
233 if (!scop)
234 return -1;
236 input_file = fopen(input, "r");
237 output_file = get_output_file(input);
239 copy_before_scop(input_file, output_file);
240 fprintf(output_file, "/* ppcg generated CPU code */\n\n");
241 print_scop(ctx, scop, output_file);
242 copy_after_scop(input_file, output_file);
244 fclose(output_file);
245 fclose(input_file);
247 return 0;