blob: 39b4a2aa44ac34c0f7a24c144ce27def7b078c24 [file] [log] [blame]
Tobias Grosser75805372011-04-29 06:27:02 +00001//===-- OpenScopExporter.cpp - Export Scops with openscop library --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Export the Scops build by ScopInfo pass to text file.
11//
12//===----------------------------------------------------------------------===//
13
14#include "polly/LinkAllPasses.h"
15
16#ifdef OPENSCOP_FOUND
17
18#include "polly/ScopInfo.h"
19#include "polly/ScopPass.h"
20
21#include "llvm/Support/CommandLine.h"
22#include "llvm/Assembly/Writer.h"
23
24#define OPENSCOP_INT_T_IS_MP
25#include "openscop/openscop.h"
26
27#include "stdio.h"
Raghesh Aloor7eb661e2011-07-09 03:10:22 +000028#include "isl/map.h"
Tobias Grosser75805372011-04-29 06:27:02 +000029#include "isl/set.h"
30#include "isl/constraint.h"
31
32using namespace llvm;
33using namespace polly;
34
35namespace {
36static cl::opt<std::string>
37ExportDir("polly-export-dir",
38 cl::desc("The directory to export the .scop files to."), cl::Hidden,
39 cl::value_desc("Directory path"), cl::ValueRequired, cl::init("."));
40
41struct ScopExporter : public ScopPass {
42 static char ID;
43 Scop *S;
44 explicit ScopExporter() : ScopPass(ID) {}
45
46 std::string getFileName(Scop *S) const;
47
48 virtual bool runOnScop(Scop &S);
49 void printScop(raw_ostream &OS) const;
50 void getAnalysisUsage(AnalysisUsage &AU) const;
51};
52
53}
54
55char ScopExporter::ID = 0;
56
57class OpenScop {
58 Scop *PollyScop;
59 openscop_scop_p openscop;
60
61 std::map<const Value*, int> ArrayMap;
62
63 void initializeArrays();
64 void initializeParameters();
65 void initializeScattering();
66 void initializeStatements();
67 openscop_statement_p initializeStatement(ScopStmt *stmt);
68 void freeStatement(openscop_statement_p stmt);
69 static int accessToMatrix_constraint(isl_constraint *c, void *user);
70 static int accessToMatrix_basic_map(isl_basic_map *bmap, void *user);
71 openscop_matrix_p createAccessMatrix(ScopStmt *S, bool isRead);
72 static int domainToMatrix_constraint(isl_constraint *c, void *user);
73 static int domainToMatrix_basic_set(isl_basic_set *bset, void *user);
74 openscop_matrix_p domainToMatrix(isl_set *PS);
75 static int scatteringToMatrix_constraint(isl_constraint *c, void *user);
76 static int scatteringToMatrix_basic_map(isl_basic_map *bmap, void *user);
77 openscop_matrix_p scatteringToMatrix(isl_map *pmap);
78
79public:
80 OpenScop(Scop *S);
81 ~OpenScop();
82 void print(FILE *F);
83
84};
85
86OpenScop::OpenScop(Scop *S) : PollyScop(S) {
87 openscop = openscop_scop_malloc();
88
89 initializeArrays();
90 initializeParameters();
91 initializeScattering();
92 initializeStatements();
93}
94
95void OpenScop::initializeParameters() {
96 openscop->nb_parameters = PollyScop->getNumParams();
97 openscop->parameters = new char*[openscop->nb_parameters];
98
99 for (int i = 0; i < openscop->nb_parameters; ++i) {
100 openscop->parameters[i] = new char[20];
101 sprintf(openscop->parameters[i], "p_%d", i);
102 }
103}
104
105void OpenScop::initializeArrays() {
106 int nb_arrays = 0;
107
108 for (Scop::iterator SI = PollyScop->begin(), SE = PollyScop->end(); SI != SE;
109 ++SI)
110 for (ScopStmt::memacc_iterator MI = (*SI)->memacc_begin(),
111 ME = (*SI)->memacc_end(); MI != ME; ++MI) {
112 const Value *BaseAddr = (*MI)->getBaseAddr();
113 if (ArrayMap.find(BaseAddr) == ArrayMap.end()) {
114 ArrayMap.insert(std::make_pair(BaseAddr, nb_arrays));
115 ++nb_arrays;
116 }
117 }
118
119 openscop->nb_arrays = nb_arrays;
120 openscop->arrays = new char*[nb_arrays];
121
122 for (int i = 0; i < nb_arrays; ++i)
123 for (std::map<const Value*, int>::iterator VI = ArrayMap.begin(),
124 VE = ArrayMap.end(); VI != VE; ++VI)
125 if ((*VI).second == i) {
126 const Value *V = (*VI).first;
Tobias Grosser34525d32011-11-22 19:40:28 +0000127 std::string name = V->getName();
Tobias Grosser75805372011-04-29 06:27:02 +0000128 openscop->arrays[i] = new char[name.size() + 1];
129 strcpy(openscop->arrays[i], name.c_str());
130 }
131}
132
133void OpenScop::initializeScattering() {
134 openscop->nb_scattdims = PollyScop->getScatterDim();
135 openscop->scattdims = new char*[openscop->nb_scattdims];
136
137 for (int i = 0; i < openscop->nb_scattdims; ++i) {
138 openscop->scattdims[i] = new char[20];
139 sprintf(openscop->scattdims[i], "s_%d", i);
140 }
141}
142
143openscop_statement_p OpenScop::initializeStatement(ScopStmt *stmt) {
144 openscop_statement_p Stmt = openscop_statement_malloc();
145
146 // Domain & Schedule
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +0000147 isl_set *domain = stmt->getDomain();
148 Stmt->domain = domainToMatrix(domain);
Tobias Grossercf3942d2011-10-06 00:04:05 +0000149 isl_map *Scattering = stmt->getScattering();
150 Stmt->schedule = scatteringToMatrix(Scattering);
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +0000151 isl_set_free(domain);
Tobias Grossercf3942d2011-10-06 00:04:05 +0000152 isl_map_free(Scattering);
153
Tobias Grosser75805372011-04-29 06:27:02 +0000154
155 // Statement name
Tobias Grosser7ffe4e82011-11-17 12:56:10 +0000156 const char *entryName = stmt->getBaseName();
Tobias Grosser75805372011-04-29 06:27:02 +0000157 Stmt->body = (char*)malloc(sizeof(char) * (strlen(entryName) + 1));
158 strcpy(Stmt->body, entryName);
159
160 // Iterator names
161 Stmt->nb_iterators = isl_set_n_dim(stmt->getDomain());
162 Stmt->iterators = new char*[Stmt->nb_iterators];
163
164 for (int i = 0; i < Stmt->nb_iterators; ++i) {
165 Stmt->iterators[i] = new char[20];
166 sprintf(Stmt->iterators[i], "i_%d", i);
167 }
168
169 // Memory Accesses
170 Stmt->read = createAccessMatrix(stmt, true);
171 Stmt->write = createAccessMatrix(stmt, false);
172
173 return Stmt;
174}
175
176void OpenScop::initializeStatements() {
177 for (Scop::reverse_iterator SI = PollyScop->rbegin(), SE = PollyScop->rend();
178 SI != SE; ++SI) {
Tobias Grosser75805372011-04-29 06:27:02 +0000179 openscop_statement_p stmt = initializeStatement(*SI);
180 stmt->next = openscop->statement;
181 openscop->statement = stmt;
182 }
183}
184
185void OpenScop::freeStatement(openscop_statement_p stmt) {
186
187 if (stmt->read)
188 openscop_matrix_free(stmt->read);
189 stmt->read = NULL;
190
191 if (stmt->write)
192 openscop_matrix_free(stmt->write);
193 stmt->write = NULL;
194
195 if (stmt->domain)
196 openscop_matrix_free(stmt->domain);
197 stmt->domain = NULL;
198
199 if (stmt->schedule)
200 openscop_matrix_free(stmt->schedule);
201 stmt->schedule = NULL;
202
203 for (int i = 0; i < stmt->nb_iterators; ++i)
204 delete[](stmt->iterators[i]);
205
206 delete[](stmt->iterators);
207 stmt->iterators = NULL;
208 stmt->nb_iterators = 0;
209
210 delete[](stmt->body);
211 stmt->body = NULL;
212
213 openscop_statement_free(stmt);
214}
215
216void OpenScop::print(FILE *F) {
217 openscop_scop_print_dot_scop(F, openscop);
218}
219
220/// Add an isl constraint to an OpenScop matrix.
221///
222/// @param user The matrix
223/// @param c The constraint
224int OpenScop::domainToMatrix_constraint(isl_constraint *c, void *user) {
225 openscop_matrix_p m = (openscop_matrix_p) user;
226
Tobias Grosserf5338802011-10-06 00:03:35 +0000227 int nb_params = isl_constraint_dim(c, isl_space_param);
228 int nb_vars = isl_constraint_dim(c, isl_space_set);
229 int nb_div = isl_constraint_dim(c, isl_space_div);
Tobias Grosser75805372011-04-29 06:27:02 +0000230
231 assert(!nb_div && "Existentially quantified variables not yet supported");
232
233 openscop_vector_p vec = openscop_vector_malloc(nb_params + nb_vars + 2);
234
235 // Assign type
236 if (isl_constraint_is_equality(c))
237 openscop_vector_tag_equality(vec);
238 else
239 openscop_vector_tag_inequality(vec);
240
241 isl_int v;
242 isl_int_init(v);
243
244 // Assign variables
245 for (int i = 0; i < nb_vars; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000246 isl_constraint_get_coefficient(c, isl_space_set, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000247 isl_int_set(vec->p[i + 1], v);
248 }
249
250 // Assign parameters
251 for (int i = 0; i < nb_params; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000252 isl_constraint_get_coefficient(c, isl_space_param, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000253 isl_int_set(vec->p[nb_vars + i + 1], v);
254 }
255
256 // Assign constant
257 isl_constraint_get_constant(c, &v);
258 isl_int_set(vec->p[nb_params + nb_vars + 1], v);
259
260 openscop_matrix_insert_vector(m, vec, m->NbRows);
261
262 return 0;
263}
264
265/// Add an isl basic set to a OpenScop matrix_list
266///
267/// @param bset The basic set to add
268/// @param user The matrix list we should add the basic set to
269///
270/// XXX: At the moment this function expects just a matrix, as support
271/// for matrix lists is currently not available in OpenScop. So union of
272/// polyhedron are not yet supported
273int OpenScop::domainToMatrix_basic_set(isl_basic_set *bset, void *user) {
274 openscop_matrix_p m = (openscop_matrix_p) user;
275 assert(!m->NbRows && "Union of polyhedron not yet supported");
276
277 isl_basic_set_foreach_constraint(bset, &domainToMatrix_constraint, user);
278 return 0;
279}
280
281/// Translate a isl_set to a OpenScop matrix.
282///
283/// @param PS The set to be translated
284/// @return A OpenScop Matrix
285openscop_matrix_p OpenScop::domainToMatrix(isl_set *PS) {
286
287 // Create a canonical copy of this set.
288 isl_set *set = isl_set_copy(PS);
289 set = isl_set_compute_divs (set);
290 set = isl_set_align_divs (set);
291
292 // Initialize the matrix.
293 unsigned NbRows, NbColumns;
294 NbRows = 0;
295 NbColumns = isl_set_n_dim(PS) + isl_set_n_param(PS) + 2;
296 openscop_matrix_p matrix = openscop_matrix_malloc(NbRows, NbColumns);
297
298 // Copy the content into the matrix.
299 isl_set_foreach_basic_set(set, &domainToMatrix_basic_set, matrix);
300
301 isl_set_free(set);
302
303 return matrix;
304}
305
306/// Add an isl constraint to an OpenScop matrix.
307///
308/// @param user The matrix
309/// @param c The constraint
310int OpenScop::scatteringToMatrix_constraint(isl_constraint *c, void *user) {
311 openscop_matrix_p m = (openscop_matrix_p) user;
312
Tobias Grosserf5338802011-10-06 00:03:35 +0000313 int nb_params = isl_constraint_dim(c, isl_space_param);
314 int nb_in = isl_constraint_dim(c, isl_space_in);
315 int nb_out = isl_constraint_dim(c, isl_space_out);
316 int nb_div = isl_constraint_dim(c, isl_space_div);
Tobias Grosser75805372011-04-29 06:27:02 +0000317
318 assert(!nb_div && "Existentially quantified variables not yet supported");
319
320 openscop_vector_p vec =
321 openscop_vector_malloc(nb_params + nb_in + nb_out + 2);
322
323 // Assign type
324 if (isl_constraint_is_equality(c))
325 openscop_vector_tag_equality(vec);
326 else
327 openscop_vector_tag_inequality(vec);
328
329 isl_int v;
330 isl_int_init(v);
331
332 // Assign scattering
333 for (int i = 0; i < nb_out; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000334 isl_constraint_get_coefficient(c, isl_space_out, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000335 isl_int_set(vec->p[i + 1], v);
336 }
337
338 // Assign variables
339 for (int i = 0; i < nb_in; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000340 isl_constraint_get_coefficient(c, isl_space_in, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000341 isl_int_set(vec->p[nb_out + i + 1], v);
342 }
343
344 // Assign parameters
345 for (int i = 0; i < nb_params; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000346 isl_constraint_get_coefficient(c, isl_space_param, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000347 isl_int_set(vec->p[nb_out + nb_in + i + 1], v);
348 }
349
350 // Assign constant
351 isl_constraint_get_constant(c, &v);
352 isl_int_set(vec->p[nb_out + nb_in + nb_params + 1], v);
353
354 openscop_matrix_insert_vector(m, vec, m->NbRows);
355
356 return 0;
357}
358
359/// Add an isl basic map to a OpenScop matrix_list
360///
361/// @param bmap The basic map to add
362/// @param user The matrix list we should add the basic map to
363///
364/// XXX: At the moment this function expects just a matrix, as support
365/// for matrix lists is currently not available in OpenScop. So union of
366/// polyhedron are not yet supported
367int OpenScop::scatteringToMatrix_basic_map(isl_basic_map *bmap, void *user) {
368 openscop_matrix_p m = (openscop_matrix_p) user;
369 assert(!m->NbRows && "Union of polyhedron not yet supported");
370
371 isl_basic_map_foreach_constraint(bmap, &scatteringToMatrix_constraint, user);
372 return 0;
373}
374
375/// Translate a isl_map to a OpenScop matrix.
376///
377/// @param map The map to be translated
378/// @return A OpenScop Matrix
379openscop_matrix_p OpenScop::scatteringToMatrix(isl_map *pmap) {
380
381 // Create a canonical copy of this set.
382 isl_map *map = isl_map_copy(pmap);
383 map = isl_map_compute_divs (map);
384 map = isl_map_align_divs (map);
385
386 // Initialize the matrix.
387 unsigned NbRows, NbColumns;
388 NbRows = 0;
389 NbColumns = isl_map_n_in(pmap) + isl_map_n_out(pmap) + isl_map_n_param(pmap)
390 + 2;
391 openscop_matrix_p matrix = openscop_matrix_malloc(NbRows, NbColumns);
392
393 // Copy the content into the matrix.
394 isl_map_foreach_basic_map(map, &scatteringToMatrix_basic_map, matrix);
395
396 isl_map_free(map);
397
398 return matrix;
399}
400
401/// Add an isl constraint to an OpenScop matrix.
402///
403/// @param user The matrix
404/// @param c The constraint
405int OpenScop::accessToMatrix_constraint(isl_constraint *c, void *user) {
406 openscop_matrix_p m = (openscop_matrix_p) user;
407
Tobias Grosserf5338802011-10-06 00:03:35 +0000408 int nb_params = isl_constraint_dim(c, isl_space_param);
409 int nb_in = isl_constraint_dim(c, isl_space_in);
410 int nb_div = isl_constraint_dim(c, isl_space_div);
Tobias Grosser75805372011-04-29 06:27:02 +0000411
412 assert(!nb_div && "Existentially quantified variables not yet supported");
413
414 openscop_vector_p vec =
415 openscop_vector_malloc(nb_params + nb_in + 2);
416
417 isl_int v;
418 isl_int_init(v);
419
420 // The access dimension has to be one.
Tobias Grosserf5338802011-10-06 00:03:35 +0000421 isl_constraint_get_coefficient(c, isl_space_out, 0, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000422 assert(isl_int_is_one(v));
423 bool inverse = true ;
424
425 // Assign variables
426 for (int i = 0; i < nb_in; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000427 isl_constraint_get_coefficient(c, isl_space_in, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000428
429 if (inverse) isl_int_neg(v,v);
430
431 isl_int_set(vec->p[i + 1], v);
432 }
433
434 // Assign parameters
435 for (int i = 0; i < nb_params; ++i) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000436 isl_constraint_get_coefficient(c, isl_space_param, i, &v);
Tobias Grosser75805372011-04-29 06:27:02 +0000437
438 if (inverse) isl_int_neg(v,v);
439
440 isl_int_set(vec->p[nb_in + i + 1], v);
441 }
442
443 // Assign constant
444 isl_constraint_get_constant(c, &v);
445
446 if (inverse) isl_int_neg(v,v);
447
448 isl_int_set(vec->p[nb_in + nb_params + 1], v);
449
450 openscop_matrix_insert_vector(m, vec, m->NbRows);
451
452 return 0;
453}
454
455
456/// Add an isl basic map to a OpenScop matrix_list
457///
458/// @param bmap The basic map to add
459/// @param user The matrix list we should add the basic map to
460///
461/// XXX: At the moment this function expects just a matrix, as support
462/// for matrix lists is currently not available in OpenScop. So union of
463/// polyhedron are not yet supported
464int OpenScop::accessToMatrix_basic_map(isl_basic_map *bmap, void *user) {
465 isl_basic_map_foreach_constraint(bmap, &accessToMatrix_constraint, user);
466 return 0;
467}
468
469/// Create the memory access matrix for openscop
470///
471/// @param S The polly statement the access matrix is created for.
472/// @param isRead Are we looking for read or write accesses?
473/// @param ArrayMap A map translating from the memory references to the openscop
474/// indeces
475///
476/// @return The memory access matrix, as it is required by openscop.
477openscop_matrix_p OpenScop::createAccessMatrix(ScopStmt *S, bool isRead) {
478
479 unsigned NbColumns = S->getNumIterators() + S->getNumParams() + 2;
480 openscop_matrix_p m = openscop_matrix_malloc(0, NbColumns);
481
482 for (ScopStmt::memacc_iterator MI = S->memacc_begin(), ME = S->memacc_end();
483 MI != ME; ++MI)
484 if ((*MI)->isRead() == isRead) {
485 // Extract the access function.
486 isl_map_foreach_basic_map((*MI)->getAccessFunction(),
487 &accessToMatrix_basic_map, m);
488
489 // Set the index of the memory access base element.
490 std::map<const Value*, int>::iterator BA =
491 ArrayMap.find((*MI)->getBaseAddr());
492 isl_int_set_si(m->p[m->NbRows - 1][0], (*BA).second + 1);
493 }
494
495 return m;
496}
497
498OpenScop::~OpenScop() {
499 // Free array names.
500 for (int i = 0; i < openscop->nb_arrays; ++i)
501 delete[](openscop->arrays[i]);
502
503 delete[](openscop->arrays);
504 openscop->arrays = NULL;
505 openscop->nb_arrays = 0;
506
507 // Free scattering names.
508 for (int i = 0; i < openscop->nb_scattdims; ++i)
509 delete[](openscop->scattdims[i]);
510
511 delete[](openscop->scattdims);
512 openscop->scattdims = NULL;
513 openscop->nb_scattdims = 0;
514
515 // Free parameters
516 for (int i = 0; i < openscop->nb_parameters; ++i)
517 delete[](openscop->parameters[i]);
518
519 delete[](openscop->parameters);
520 openscop->parameters = NULL;
521 openscop->nb_parameters = 0;
522
523 openscop_statement_p stmt = openscop->statement;
524
525 // Free Statements
526 while (stmt) {
527 openscop_statement_p TempStmt = stmt->next;
528 stmt->next = NULL;
529 freeStatement(stmt);
530 stmt = TempStmt;
531 }
532
533 openscop->statement = NULL;
534
535 openscop_scop_free(openscop);
536}
537
538std::string ScopExporter::getFileName(Scop *S) const {
539 std::string FunctionName =
Tobias Grosser34525d32011-11-22 19:40:28 +0000540 S->getRegion().getEntry()->getParent()->getName();
Tobias Grosser75805372011-04-29 06:27:02 +0000541 std::string FileName = FunctionName + "___" + S->getNameStr() + ".scop";
542 return FileName;
543}
544
545void ScopExporter::printScop(raw_ostream &OS) const {
546 S->print(OS);
547}
548
549bool ScopExporter::runOnScop(Scop &scop) {
550 S = &scop;
551 Region &R = S->getRegion();
552
553 std::string FileName = ExportDir + "/" + getFileName(S);
554 FILE *F = fopen(FileName.c_str(), "w");
555
556 if (!F) {
557 errs() << "Cannot open file: " << FileName << "\n";
558 errs() << "Skipping export.\n";
559 return false;
560 }
561
562 OpenScop openscop(S);
563 openscop.print(F);
564 fclose(F);
565
Tobias Grosser34525d32011-11-22 19:40:28 +0000566 std::string FunctionName = R.getEntry()->getParent()->getName();
Tobias Grosser75805372011-04-29 06:27:02 +0000567 errs() << "Writing Scop '" << R.getNameStr() << "' in function '"
568 << FunctionName << "' to '" << FileName << "'.\n";
569
570 return false;
571}
572
573void ScopExporter::getAnalysisUsage(AnalysisUsage &AU) const {
574 ScopPass::getAnalysisUsage(AU);
575}
576
577static RegisterPass<ScopExporter> A("polly-export",
578 "Polly - Export Scops with OpenScop library"
579 " (Writes a .scop file for each Scop)"
580 );
581
582Pass *polly::createScopExporterPass() {
583 return new ScopExporter();
584}
585
586#endif
587