blob: 71c7efb8f3c3d37f19bd375514cc5fedf91f2012 [file] [log] [blame]
Tobias Grosser75805372011-04-29 06:27:02 +00001//===--------- ScopInfo.cpp - Create Scops from LLVM IR ------------------===//
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// Create a polyhedral description for a static control flow region.
11//
12// The pass creates a polyhedral description of the Scops detected by the Scop
13// detection derived from their LLVM-IR code.
14//
15// This represantation is shared among several tools in the polyhedral
16// community, which are e.g. Cloog, Pluto, Loopo, Graphite.
17//
18//===----------------------------------------------------------------------===//
19
20#include "polly/ScopInfo.h"
21
22#include "polly/TempScopInfo.h"
23#include "polly/LinkAllPasses.h"
24#include "polly/Support/GICHelper.h"
25#include "polly/Support/ScopHelper.h"
26
27#include "llvm/Analysis/LoopInfo.h"
28#include "llvm/Analysis/ScalarEvolutionExpressions.h"
29#include "llvm/Analysis/RegionIterator.h"
30#include "llvm/Assembly/Writer.h"
31#include "llvm/ADT/Statistic.h"
32#include "llvm/ADT/SetVector.h"
33#include "llvm/Support/CommandLine.h"
34
35#define DEBUG_TYPE "polly-scops"
36#include "llvm/Support/Debug.h"
37
38#include "isl/constraint.h"
39#include "isl/set.h"
40#include "isl/map.h"
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000041#include "isl/aff.h"
42#include "isl/printer.h"
Tobias Grosser75805372011-04-29 06:27:02 +000043#include <sstream>
44#include <string>
45#include <vector>
46
47using namespace llvm;
48using namespace polly;
49
50STATISTIC(ScopFound, "Number of valid Scops");
51STATISTIC(RichScopFound, "Number of Scops containing a loop");
52
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000053/// Convert an int into a string.
54static std::string convertInt(int number)
55{
56 if (number == 0)
57 return "0";
58 std::string temp = "";
59 std::string returnvalue = "";
60 while (number > 0)
61 {
62 temp += number % 10 + 48;
63 number /= 10;
64 }
65 for (unsigned i = 0; i < temp.length(); i++)
66 returnvalue+=temp[temp.length() - i - 1];
67 return returnvalue;
Tobias Grosser75805372011-04-29 06:27:02 +000068}
69
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000070static isl_map *map_remove_dim_ids(isl_map *map) {
71 isl_ctx *ctx = isl_map_get_ctx(map);
72 int numParams = isl_map_n_param(map);
73 isl_printer *p = isl_printer_to_str(ctx);
74 char *str;
75
76 p = isl_printer_set_output_format (p, ISL_FORMAT_EXT_POLYLIB);
77 p = isl_printer_print_map(p, map);
78 isl_map_free (map);
79
80 str = isl_printer_get_str (p);
81 map = isl_map_read_from_str (ctx, str, numParams);
82 free (str);
83 isl_printer_free (p);
84 return map;
85}
86
87/// Translate a SCEVExpression into an isl_pw_aff object.
88struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff*> {
89private:
90 isl_ctx *ctx;
91 int NbLoopDims;
92 const Scop *scop;
93
94 /// baseAdress is set if we analyze a memory access. It holds the base address
95 /// of this memory access.
96 const Value *baseAddress;
97
98public:
99 static isl_pw_aff *getPwAff(const ScopStmt *stmt, const SCEV *scev,
100 const Value *baseAddress) {
101 SCEVAffinator Affinator(stmt, baseAddress);
102 return Affinator.visit(scev);
103 }
104
105 isl_pw_aff *visit(const SCEV *scev) {
106 // In case the scev is contained in our list of parameters, we do not
107 // further analyze this expression, but create a new parameter in the
108 // isl_pw_aff. This allows us to treat subexpressions that we cannot
109 // translate into an piecewise affine expression, as constant parameters of
110 // the piecewise affine expression.
111 int i = 0;
112 for (Scop::const_param_iterator PI = scop->param_begin(),
113 PE = scop->param_end(); PI != PE; ++PI) {
114 if (*PI == scev) {
115 isl_id *ID = isl_id_alloc(ctx, ("p" + convertInt(i)).c_str(),
116 (void *) scev);
117 isl_dim *Dim = isl_dim_set_alloc(ctx, 1, NbLoopDims);
118 Dim = isl_dim_set_dim_id(Dim, isl_dim_param, 0, ID);
119
120 isl_set *Domain = isl_set_universe(isl_dim_copy(Dim));
121 isl_aff *Affine = isl_aff_zero(isl_local_space_from_dim(Dim));
122 Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
123
124 return isl_pw_aff_alloc(Domain, Affine);
125 }
126 i++;
127 }
128
129 return SCEVVisitor<SCEVAffinator, isl_pw_aff*>::visit(scev);
130 }
131
132 SCEVAffinator(const ScopStmt *stmt, const Value *baseAddress) :
133 ctx(stmt->getParent()->getCtx()),
134 NbLoopDims(stmt->getNumIterators()),
135 scop(stmt->getParent()),
136 baseAddress(baseAddress) {};
137
138 __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Constant) {
139 ConstantInt *Value = Constant->getValue();
140 isl_int v;
141 isl_int_init(v);
142
143 // LLVM does not define if an integer value is interpreted as a signed or
144 // unsigned value. Hence, without further information, it is unknown how
145 // this value needs to be converted to GMP. At the moment, we only support
146 // signed operations. So we just interpret it as signed. Later, there are
147 // two options:
148 //
149 // 1. We always interpret any value as signed and convert the values on
150 // demand.
151 // 2. We pass down the signedness of the calculation and use it to interpret
152 // this constant correctly.
153 MPZ_from_APInt(v, Value->getValue(), /* isSigned */ true);
154
155 isl_dim *dim = isl_dim_set_alloc(ctx, 0, NbLoopDims);
156 isl_local_space *ls = isl_local_space_from_dim(isl_dim_copy(dim));
157 isl_aff *Affine = isl_aff_zero(ls);
158 isl_set *Domain = isl_set_universe(dim);
159
160 Affine = isl_aff_add_constant(Affine, v);
161 isl_int_clear(v);
162
163 return isl_pw_aff_alloc(Domain, Affine);
164 }
165
166 __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr* Expr) {
167 assert(0 && "Not yet supported");
168 }
169
170 __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr * Expr) {
171 assert(0 && "Not yet supported");
172 }
173
174 __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr* Expr) {
175 // Assuming the value is signed, a sign extension is basically a noop.
176 // TODO: Reconsider this as soon as we support unsigned values.
177 return visit(Expr->getOperand());
178 }
179
180 __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr* Expr) {
181 isl_pw_aff *Sum = visit(Expr->getOperand(0));
182
183 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
184 isl_pw_aff *NextSummand = visit(Expr->getOperand(i));
185 Sum = isl_pw_aff_add(Sum, NextSummand);
186 }
187
188 // TODO: Check for NSW and NUW.
189
190 return Sum;
191 }
192
193 __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr* Expr) {
194 isl_pw_aff *Product = visit(Expr->getOperand(0));
195
196 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
197 isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
198
199 if (!isl_pw_aff_is_cst(Product) && !isl_pw_aff_is_cst(NextOperand)) {
200 isl_pw_aff_free(Product);
201 isl_pw_aff_free(NextOperand);
202 return NULL;
203 }
204
205 Product = isl_pw_aff_mul(Product, NextOperand);
206 }
207
208 // TODO: Check for NSW and NUW.
209 return Product;
210 }
211
212 __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr* Expr) {
213 assert(0 && "Not yet supported");
214 }
215
216 int getLoopDepth(const Loop *L) {
217 Loop *outerLoop =
218 scop->getRegion().outermostLoopInRegion(const_cast<Loop*>(L));
219 return L->getLoopDepth() - outerLoop->getLoopDepth();
220 }
221
222 __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr* Expr) {
223 assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
224
225 isl_pw_aff *Start = visit(Expr->getStart());
226 isl_pw_aff *Step = visit(Expr->getOperand(1));
227 isl_dim *Dim = isl_dim_set_alloc (ctx, 0, NbLoopDims);
228 isl_local_space *LocalSpace = isl_local_space_from_dim (Dim);
229
230 int loopDimension = getLoopDepth(Expr->getLoop());
231
232 isl_aff *LAff = isl_aff_set_coefficient_si (isl_aff_zero (LocalSpace),
233 isl_dim_set, loopDimension, 1);
234 isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff);
235
236 // TODO: Do we need to check for NSW and NUW?
237 return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff));
238 }
239
240 __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr* Expr) {
241 isl_pw_aff *Max = visit(Expr->getOperand(0));
242
243 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
244 isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
245 Max = isl_pw_aff_max(Max, NextOperand);
246 }
247
248 return Max;
249 }
250
251 __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr* Expr) {
252 assert(0 && "Not yet supported");
253 }
254
255 __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown* Expr) {
256 Value *Value = Expr->getValue();
257
258 isl_dim *Dim;
259
260 /// If baseAddress is set, we ignore its Value object in the scev and do not
261 /// add it to the isl_pw_aff. This is because it is regarded as defining the
262 /// name of an array, in contrast to its array subscript.
263 if (baseAddress != Value) {
264 isl_id *ID = isl_id_alloc(ctx, Value->getNameStr().c_str(), Value);
265 Dim = isl_dim_set_alloc(ctx, 1, NbLoopDims);
266 Dim = isl_dim_set_dim_id(Dim, isl_dim_param, 0, ID);
267 } else {
268 Dim = isl_dim_set_alloc(ctx, 0, NbLoopDims);
269 }
270
271 isl_set *Domain = isl_set_universe(isl_dim_copy(Dim));
272 isl_aff *Affine = isl_aff_zero(isl_local_space_from_dim(Dim));
273
274 if (baseAddress != Value)
275 Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
276
277 return isl_pw_aff_alloc(Domain, Affine);
278 }
279};
280
Tobias Grosser75805372011-04-29 06:27:02 +0000281static isl_map *getValueOf(const SCEVAffFunc &AffFunc,
282 const ScopStmt *Statement, isl_dim *dim) {
Tobias Grosser75805372011-04-29 06:27:02 +0000283 assert((AffFunc.getType() == SCEVAffFunc::Eq
284 || AffFunc.getType() == SCEVAffFunc::ReadMem
285 || AffFunc.getType() == SCEVAffFunc::WriteMem)
286 && "AffFunc is not an equality");
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000287 isl_pw_aff *Affine = SCEVAffinator::getPwAff(Statement, AffFunc.OriginalSCEV,
288 AffFunc.getBaseAddr());
289 isl_map *Map = isl_map_from_pw_aff(Affine);
290 isl_dim *CtxDim = isl_set_get_dim(Statement->getParent()->getContext());
Tobias Grosser75805372011-04-29 06:27:02 +0000291
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000292 int i = 0;
293 for (Scop::const_param_iterator PI = Statement->getParent()->param_begin(),
294 PE = Statement->getParent()->param_end(); PI != PE; ++PI) {
295 const SCEV *scev = *PI;
296 isl_id *id = isl_id_alloc(isl_dim_get_ctx(CtxDim),
297 ("p" + convertInt(i)).c_str(),
298 (void *) scev);
299 CtxDim = isl_dim_set_dim_id(CtxDim, isl_dim_param, i, id);
300 i++;
Tobias Grosser75805372011-04-29 06:27:02 +0000301 }
302
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000303 isl_map_align_params(Map, CtxDim);
304 const char *dimname = isl_dim_get_tuple_name(dim, isl_dim_set);
305 Map = map_remove_dim_ids(Map);
306 Map = isl_map_set_tuple_name(Map, isl_dim_in, dimname);
307 return Map;
Tobias Grosser75805372011-04-29 06:27:02 +0000308}
309//===----------------------------------------------------------------------===//
310
311MemoryAccess::~MemoryAccess() {
Tobias Grosser54a86e62011-08-18 06:31:46 +0000312 isl_map_free(AccessRelation);
Raghesh Aloor129e8672011-08-15 02:33:39 +0000313 isl_map_free(newAccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000314}
315
316static void replace(std::string& str, const std::string& find,
317 const std::string& replace) {
318 size_t pos = 0;
319 while((pos = str.find(find, pos)) != std::string::npos)
320 {
321 str.replace(pos, find.length(), replace);
322 pos += replace.length();
323 }
324}
325
326static void makeIslCompatible(std::string& str) {
327 replace(str, ".", "_");
Tobias Grosser3b660f82011-08-03 00:12:11 +0000328 replace(str, "\"", "_");
Tobias Grosser75805372011-04-29 06:27:02 +0000329}
330
331void MemoryAccess::setBaseName() {
332 raw_string_ostream OS(BaseName);
333 WriteAsOperand(OS, getBaseAddr(), false);
334 BaseName = OS.str();
335
336 // Remove the % in the name. This is not supported by isl.
337 BaseName.erase(0,1);
338 makeIslCompatible(BaseName);
339 BaseName = "MemRef_" + BaseName;
340}
341
342std::string MemoryAccess::getAccessFunctionStr() const {
343 return stringFromIslObj(getAccessFunction());
344}
345
346isl_basic_map *MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
347 isl_dim *dim = isl_dim_alloc(Statement->getIslContext(),
348 Statement->getNumParams(),
349 Statement->getNumIterators(), 1);
350 setBaseName();
351
352 dim = isl_dim_set_tuple_name(dim, isl_dim_out, getBaseName().c_str());
353 dim = isl_dim_set_tuple_name(dim, isl_dim_in, Statement->getBaseName());
354
355 return isl_basic_map_universe(dim);
356}
357
358MemoryAccess::MemoryAccess(const SCEVAffFunc &AffFunc, ScopStmt *Statement) {
Raghesh Aloor3cb66282011-07-12 17:14:03 +0000359 newAccessRelation = NULL;
Tobias Grosser75805372011-04-29 06:27:02 +0000360 BaseAddr = AffFunc.getBaseAddr();
361 Type = AffFunc.isRead() ? Read : Write;
362 statement = Statement;
363
364 setBaseName();
365
366 isl_dim *dim = isl_dim_set_alloc(Statement->getIslContext(),
367 Statement->getNumParams(),
368 Statement->getNumIterators());
369 dim = isl_dim_set_tuple_name(dim, isl_dim_set, Statement->getBaseName());
370
371 AccessRelation = getValueOf(AffFunc, Statement, dim);
372
373 // Devide the access function by the size of the elements in the function.
374 isl_dim *dim2 = isl_dim_alloc(Statement->getIslContext(),
375 Statement->getNumParams(), 1, 1);
376 isl_basic_map *bmap = isl_basic_map_universe(isl_dim_copy(dim2));
377 isl_constraint *c = isl_equality_alloc(dim2);
378 isl_int v;
379 isl_int_init(v);
380 isl_int_set_si(v, -1);
381 isl_constraint_set_coefficient(c, isl_dim_in, 0, v);
382 isl_int_set_si(v, AffFunc.getElemSizeInBytes());
383 isl_constraint_set_coefficient(c, isl_dim_out, 0, v);
384
385 bmap = isl_basic_map_add_constraint(bmap, c);
386 isl_map* dataSizeMap = isl_map_from_basic_map(bmap);
387
388 AccessRelation = isl_map_apply_range(AccessRelation, dataSizeMap);
389
390 AccessRelation = isl_map_set_tuple_name(AccessRelation, isl_dim_out,
391 getBaseName().c_str());
392}
393
394MemoryAccess::MemoryAccess(const Value *BaseAddress, ScopStmt *Statement) {
Raghesh Aloor3cb66282011-07-12 17:14:03 +0000395 newAccessRelation = NULL;
Tobias Grosser75805372011-04-29 06:27:02 +0000396 BaseAddr = BaseAddress;
397 Type = Read;
398 statement = Statement;
399
400 isl_basic_map *BasicAccessMap = createBasicAccessMap(Statement);
401 AccessRelation = isl_map_from_basic_map(BasicAccessMap);
402}
403
404void MemoryAccess::print(raw_ostream &OS) const {
405 OS.indent(12) << (isRead() ? "Read" : "Write") << "Access := \n";
406 OS.indent(16) << getAccessFunctionStr() << ";\n";
407}
408
409void MemoryAccess::dump() const {
410 print(errs());
411}
412
413// Create a map in the size of the provided set domain, that maps from the
414// one element of the provided set domain to another element of the provided
415// set domain.
416// The mapping is limited to all points that are equal in all but the last
417// dimension and for which the last dimension of the input is strict smaller
418// than the last dimension of the output.
419//
420// getEqualAndLarger(set[i0, i1, ..., iX]):
421//
422// set[i0, i1, ..., iX] -> set[o0, o1, ..., oX]
423// : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX
424//
425static isl_map *getEqualAndLarger(isl_dim *setDomain) {
426 isl_dim *mapDomain = isl_dim_map_from_set(setDomain);
427 isl_basic_map *bmap = isl_basic_map_universe(mapDomain);
428
429 // Set all but the last dimension to be equal for the input and output
430 //
431 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX]
432 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1)
433 for (unsigned i = 0; i < isl_basic_map_n_in(bmap) - 1; ++i) {
434 isl_int v;
435 isl_int_init(v);
436 isl_constraint *c = isl_equality_alloc(isl_basic_map_get_dim(bmap));
437
438 isl_int_set_si(v, 1);
439 isl_constraint_set_coefficient(c, isl_dim_in, i, v);
440 isl_int_set_si(v, -1);
441 isl_constraint_set_coefficient(c, isl_dim_out, i, v);
442
443 bmap = isl_basic_map_add_constraint(bmap, c);
444
445 isl_int_clear(v);
446 }
447
448 // Set the last dimension of the input to be strict smaller than the
449 // last dimension of the output.
450 //
451 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX
452 //
453 unsigned lastDimension = isl_basic_map_n_in(bmap) - 1;
454 isl_int v;
455 isl_int_init(v);
456 isl_constraint *c = isl_inequality_alloc(isl_basic_map_get_dim(bmap));
457 isl_int_set_si(v, -1);
458 isl_constraint_set_coefficient(c, isl_dim_in, lastDimension, v);
459 isl_int_set_si(v, 1);
460 isl_constraint_set_coefficient(c, isl_dim_out, lastDimension, v);
461 isl_int_set_si(v, -1);
462 isl_constraint_set_constant(c, v);
463 isl_int_clear(v);
464
465 bmap = isl_basic_map_add_constraint(bmap, c);
466
467 return isl_map_from_basic_map(bmap);
468}
469
470isl_set *MemoryAccess::getStride(const isl_set *domainSubset) const {
471 isl_map *accessRelation = isl_map_copy(getAccessFunction());
472 isl_set *scatteringDomain = isl_set_copy(const_cast<isl_set*>(domainSubset));
473 isl_map *scattering = isl_map_copy(getStatement()->getScattering());
474
475 scattering = isl_map_reverse(scattering);
476 int difference = isl_map_n_in(scattering) - isl_set_n_dim(scatteringDomain);
477 scattering = isl_map_project_out(scattering, isl_dim_in,
478 isl_set_n_dim(scatteringDomain),
479 difference);
480
481 // Remove all names of the scattering dimensions, as the names may be lost
482 // anyways during the project. This leads to consistent results.
483 scattering = isl_map_set_tuple_name(scattering, isl_dim_in, "");
484 scatteringDomain = isl_set_set_tuple_name(scatteringDomain, "");
485
486 isl_map *nextScatt = getEqualAndLarger(isl_set_get_dim(scatteringDomain));
487 nextScatt = isl_map_lexmin(nextScatt);
488
489 scattering = isl_map_intersect_domain(scattering, scatteringDomain);
490
491 nextScatt = isl_map_apply_range(nextScatt, isl_map_copy(scattering));
492 nextScatt = isl_map_apply_range(nextScatt, isl_map_copy(accessRelation));
493 nextScatt = isl_map_apply_domain(nextScatt, scattering);
494 nextScatt = isl_map_apply_domain(nextScatt, accessRelation);
495
496 return isl_map_deltas(nextScatt);
497}
498
499bool MemoryAccess::isStrideZero(const isl_set *domainSubset) const {
500 isl_set *stride = getStride(domainSubset);
501 isl_constraint *c = isl_equality_alloc(isl_set_get_dim(stride));
502
503 isl_int v;
504 isl_int_init(v);
505 isl_int_set_si(v, 1);
506 isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
507 isl_int_set_si(v, 0);
508 isl_constraint_set_constant(c, v);
509 isl_int_clear(v);
510
511 isl_basic_set *bset = isl_basic_set_universe(isl_set_get_dim(stride));
512
513 bset = isl_basic_set_add_constraint(bset, c);
514 isl_set *strideZero = isl_set_from_basic_set(bset);
515
516 return isl_set_is_equal(stride, strideZero);
517}
518
519bool MemoryAccess::isStrideOne(const isl_set *domainSubset) const {
520 isl_set *stride = getStride(domainSubset);
521 isl_constraint *c = isl_equality_alloc(isl_set_get_dim(stride));
522
523 isl_int v;
524 isl_int_init(v);
525 isl_int_set_si(v, 1);
526 isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
527 isl_int_set_si(v, -1);
528 isl_constraint_set_constant(c, v);
529 isl_int_clear(v);
530
531 isl_basic_set *bset = isl_basic_set_universe(isl_set_get_dim(stride));
532
533 bset = isl_basic_set_add_constraint(bset, c);
534 isl_set *strideZero = isl_set_from_basic_set(bset);
535
536 return isl_set_is_equal(stride, strideZero);
537}
538
Raghesh Aloor7a04f4f2011-08-03 13:47:59 +0000539void MemoryAccess::setNewAccessFunction(isl_map *newAccess) {
540 newAccessRelation = newAccess;
Raghesh Aloor3cb66282011-07-12 17:14:03 +0000541}
Tobias Grosser75805372011-04-29 06:27:02 +0000542
543//===----------------------------------------------------------------------===//
544void ScopStmt::buildScattering(SmallVectorImpl<unsigned> &Scatter) {
545 unsigned NumberOfIterators = getNumIterators();
546 unsigned ScatDim = Parent.getMaxLoopDepth() * 2 + 1;
547 isl_dim *dim = isl_dim_alloc(Parent.getCtx(), Parent.getNumParams(),
548 NumberOfIterators, ScatDim);
549 dim = isl_dim_set_tuple_name(dim, isl_dim_out, "scattering");
550 dim = isl_dim_set_tuple_name(dim, isl_dim_in, getBaseName());
551 isl_basic_map *bmap = isl_basic_map_universe(isl_dim_copy(dim));
552 isl_int v;
553 isl_int_init(v);
554
555 // Loop dimensions.
556 for (unsigned i = 0; i < NumberOfIterators; ++i) {
557 isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
558 isl_int_set_si(v, 1);
559 isl_constraint_set_coefficient(c, isl_dim_out, 2 * i + 1, v);
560 isl_int_set_si(v, -1);
561 isl_constraint_set_coefficient(c, isl_dim_in, i, v);
562
563 bmap = isl_basic_map_add_constraint(bmap, c);
564 }
565
566 // Constant dimensions
567 for (unsigned i = 0; i < NumberOfIterators + 1; ++i) {
568 isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
569 isl_int_set_si(v, -1);
570 isl_constraint_set_coefficient(c, isl_dim_out, 2 * i, v);
571 isl_int_set_si(v, Scatter[i]);
572 isl_constraint_set_constant(c, v);
573
574 bmap = isl_basic_map_add_constraint(bmap, c);
575 }
576
577 // Fill scattering dimensions.
578 for (unsigned i = 2 * NumberOfIterators + 1; i < ScatDim ; ++i) {
579 isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
580 isl_int_set_si(v, 1);
581 isl_constraint_set_coefficient(c, isl_dim_out, i, v);
582 isl_int_set_si(v, 0);
583 isl_constraint_set_constant(c, v);
584
585 bmap = isl_basic_map_add_constraint(bmap, c);
586 }
587
588 isl_int_clear(v);
589 isl_dim_free(dim);
590 Scattering = isl_map_from_basic_map(bmap);
591}
592
593void ScopStmt::buildAccesses(TempScop &tempScop, const Region &CurRegion) {
594 const AccFuncSetType *AccFuncs = tempScop.getAccessFunctions(BB);
595
596 for (AccFuncSetType::const_iterator I = AccFuncs->begin(),
597 E = AccFuncs->end(); I != E; ++I) {
598 MemAccs.push_back(new MemoryAccess(I->first, this));
599 InstructionToAccess[I->second] = MemAccs.back();
600 }
601}
602
603static isl_map *MapValueToLHS(isl_ctx *Context, unsigned ParameterNumber) {
604 std::string MapString;
605 isl_map *Map;
606
607 MapString = "{[i0] -> [i0, o1]}";
608 Map = isl_map_read_from_str(Context, MapString.c_str(), -1);
609 return isl_map_add_dims(Map, isl_dim_param, ParameterNumber);
610}
611
612static isl_map *MapValueToRHS(isl_ctx *Context, unsigned ParameterNumber) {
613 std::string MapString;
614 isl_map *Map;
615
616 MapString = "{[i0] -> [o0, i0]}";
617 Map = isl_map_read_from_str(Context, MapString.c_str(), -1);
618 return isl_map_add_dims(Map, isl_dim_param, ParameterNumber);
619}
620
621static isl_set *getComparison(isl_ctx *Context, const ICmpInst::Predicate Pred,
622 unsigned ParameterNumber) {
623 std::string SetString;
624
625 switch (Pred) {
626 case ICmpInst::ICMP_EQ:
627 SetString = "{[i0, i1] : i0 = i1}";
628 break;
629 case ICmpInst::ICMP_NE:
630 SetString = "{[i0, i1] : i0 + 1 <= i1; [i0, i1] : i0 - 1 >= i1}";
631 break;
632 case ICmpInst::ICMP_SLT:
633 SetString = "{[i0, i1] : i0 + 1 <= i1}";
634 break;
635 case ICmpInst::ICMP_ULT:
636 SetString = "{[i0, i1] : i0 + 1 <= i1}";
637 break;
638 case ICmpInst::ICMP_SGT:
639 SetString = "{[i0, i1] : i0 >= i1 + 1}";
640 break;
641 case ICmpInst::ICMP_UGT:
642 SetString = "{[i0, i1] : i0 >= i1 + 1}";
643 break;
644 case ICmpInst::ICMP_SLE:
645 SetString = "{[i0, i1] : i0 <= i1}";
646 break;
647 case ICmpInst::ICMP_ULE:
648 SetString = "{[i0, i1] : i0 <= i1}";
649 break;
650 case ICmpInst::ICMP_SGE:
651 SetString = "{[i0, i1] : i0 >= i1}";
652 break;
653 case ICmpInst::ICMP_UGE:
654 SetString = "{[i0, i1] : i0 >= i1}";
655 break;
656 default:
657 llvm_unreachable("Non integer predicate not supported");
658 }
659
660 isl_set *Set = isl_set_read_from_str(Context, SetString.c_str(), -1);
661 return isl_set_add_dims(Set, isl_dim_param, ParameterNumber);
662}
663
664static isl_set *compareValues(isl_map *LeftValue, isl_map *RightValue,
665 const ICmpInst::Predicate Predicate) {
666 isl_ctx *Context = isl_map_get_ctx(LeftValue);
667 unsigned NumberOfParameters = isl_map_n_param(LeftValue);
668
669 isl_map *MapToLHS = MapValueToLHS(Context, NumberOfParameters);
670 isl_map *MapToRHS = MapValueToRHS(Context, NumberOfParameters);
671
672 isl_map *LeftValueAtLHS = isl_map_apply_range(LeftValue, MapToLHS);
673 isl_map *RightValueAtRHS = isl_map_apply_range(RightValue, MapToRHS);
674
675 isl_map *BothValues = isl_map_intersect(LeftValueAtLHS, RightValueAtRHS);
676 isl_set *Comparison = getComparison(Context, Predicate, NumberOfParameters);
677
678 isl_map *ComparedValues = isl_map_intersect_range(BothValues, Comparison);
679 return isl_map_domain(ComparedValues);
680}
681
682isl_set *ScopStmt::toConditionSet(const Comparison &Comp, isl_dim *dim) const {
683 isl_map *LHSValue = getValueOf(*Comp.getLHS(), this, dim);
684 isl_map *RHSValue = getValueOf(*Comp.getRHS(), this, dim);
685
686 return compareValues(LHSValue, RHSValue, Comp.getPred());
687}
688
689isl_set *ScopStmt::toUpperLoopBound(const SCEVAffFunc &UpperBound, isl_dim *dim,
690 unsigned BoundedDimension) const {
691 // Set output dimension to bounded dimension.
692 isl_dim *RHSDim = isl_dim_alloc(Parent.getCtx(), getNumParams(),
693 getNumIterators(), 1);
694 RHSDim = isl_dim_set_tuple_name(RHSDim, isl_dim_in, getBaseName());
695 isl_constraint *c = isl_equality_alloc(isl_dim_copy(RHSDim));
696 isl_int v;
697 isl_int_init(v);
698 isl_int_set_si(v, 1);
699 isl_constraint_set_coefficient(c, isl_dim_in, BoundedDimension, v);
700 isl_int_set_si(v, -1);
701 isl_constraint_set_coefficient(c, isl_dim_out, 0, v);
702 isl_int_clear(v);
703 isl_basic_map *bmap = isl_basic_map_universe(RHSDim);
704 bmap = isl_basic_map_add_constraint(bmap, c);
705
706 isl_map *LHSValue = isl_map_from_basic_map(bmap);
707
708 isl_map *RHSValue = getValueOf(UpperBound, this, dim);
709
710 return compareValues(LHSValue, RHSValue, ICmpInst::ICMP_SLE);
711}
712
713void ScopStmt::buildIterationDomainFromLoops(TempScop &tempScop) {
714 isl_dim *dim = isl_dim_set_alloc(Parent.getCtx(), getNumParams(),
715 getNumIterators());
716 dim = isl_dim_set_tuple_name(dim, isl_dim_set, getBaseName());
717
718 Domain = isl_set_universe(isl_dim_copy(dim));
719
720 isl_int v;
721 isl_int_init(v);
722
723 for (int i = 0, e = getNumIterators(); i != e; ++i) {
724 // Lower bound: IV >= 0.
725 isl_basic_set *bset = isl_basic_set_universe(isl_dim_copy(dim));
726 isl_constraint *c = isl_inequality_alloc(isl_dim_copy(dim));
727 isl_int_set_si(v, 1);
728 isl_constraint_set_coefficient(c, isl_dim_set, i, v);
729 bset = isl_basic_set_add_constraint(bset, c);
730 Domain = isl_set_intersect(Domain, isl_set_from_basic_set(bset));
731
732 // Upper bound: IV <= NumberOfIterations.
Hongbin Zheng27f3afb2011-04-30 03:26:51 +0000733 const Loop *L = getLoopForDimension(i);
Tobias Grosser75805372011-04-29 06:27:02 +0000734 const SCEVAffFunc &UpperBound = tempScop.getLoopBound(L);
735 isl_set *UpperBoundSet = toUpperLoopBound(UpperBound, isl_dim_copy(dim), i);
736 Domain = isl_set_intersect(Domain, UpperBoundSet);
737 }
738
739 isl_int_clear(v);
740}
741
742void ScopStmt::addConditionsToDomain(TempScop &tempScop,
743 const Region &CurRegion) {
744 isl_dim *dim = isl_set_get_dim(Domain);
745 const Region *TopR = tempScop.getMaxRegion().getParent(),
746 *CurR = &CurRegion;
747 const BasicBlock *CurEntry = BB;
748
749 // Build BB condition constrains, by traveling up the region tree.
750 do {
751 assert(CurR && "We exceed the top region?");
752 // Skip when multiple regions share the same entry.
753 if (CurEntry != CurR->getEntry()) {
754 if (const BBCond *Cnd = tempScop.getBBCond(CurEntry))
755 for (BBCond::const_iterator I = Cnd->begin(), E = Cnd->end();
756 I != E; ++I) {
757 isl_set *c = toConditionSet(*I, dim);
758 Domain = isl_set_intersect(Domain, c);
759 }
760 }
761 CurEntry = CurR->getEntry();
762 CurR = CurR->getParent();
763 } while (TopR != CurR);
764
765 isl_dim_free(dim);
766}
767
768void ScopStmt::buildIterationDomain(TempScop &tempScop, const Region &CurRegion)
769{
770 buildIterationDomainFromLoops(tempScop);
771 addConditionsToDomain(tempScop, CurRegion);
772}
773
774ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop,
775 const Region &CurRegion, BasicBlock &bb,
776 SmallVectorImpl<Loop*> &NestLoops,
777 SmallVectorImpl<unsigned> &Scatter)
778 : Parent(parent), BB(&bb), IVS(NestLoops.size()) {
779 // Setup the induction variables.
780 for (unsigned i = 0, e = NestLoops.size(); i < e; ++i) {
781 PHINode *PN = NestLoops[i]->getCanonicalInductionVariable();
782 assert(PN && "Non canonical IV in Scop!");
Hongbin Zheng27f3afb2011-04-30 03:26:51 +0000783 IVS[i] = std::make_pair(PN, NestLoops[i]);
Tobias Grosser75805372011-04-29 06:27:02 +0000784 }
785
786 raw_string_ostream OS(BaseName);
787 WriteAsOperand(OS, &bb, false);
788 BaseName = OS.str();
789
790 // Remove the % in the name. This is not supported by isl.
791 BaseName.erase(0, 1);
792 makeIslCompatible(BaseName);
793 BaseName = "Stmt_" + BaseName;
794
795 buildIterationDomain(tempScop, CurRegion);
796 buildScattering(Scatter);
797 buildAccesses(tempScop, CurRegion);
798
799 IsReduction = tempScop.is_Reduction(*BB);
800}
801
802ScopStmt::ScopStmt(Scop &parent, SmallVectorImpl<unsigned> &Scatter)
803 : Parent(parent), BB(NULL), IVS(0) {
804
805 BaseName = "FinalRead";
806
807 // Build iteration domain.
808 std::string IterationDomainString = "{[i0] : i0 = 0}";
809 Domain = isl_set_read_from_str(Parent.getCtx(), IterationDomainString.c_str(),
810 -1);
811 Domain = isl_set_add_dims(Domain, isl_dim_param, Parent.getNumParams());
812 Domain = isl_set_set_tuple_name(Domain, getBaseName());
813
814 // Build scattering.
815 unsigned ScatDim = Parent.getMaxLoopDepth() * 2 + 1;
816 isl_dim *dim = isl_dim_alloc(Parent.getCtx(), Parent.getNumParams(), 1,
817 ScatDim);
818 dim = isl_dim_set_tuple_name(dim, isl_dim_out, "scattering");
819 dim = isl_dim_set_tuple_name(dim, isl_dim_in, getBaseName());
820 isl_basic_map *bmap = isl_basic_map_universe(isl_dim_copy(dim));
821 isl_int v;
822 isl_int_init(v);
823
824 isl_constraint *c = isl_equality_alloc(dim);
825 isl_int_set_si(v, -1);
826 isl_constraint_set_coefficient(c, isl_dim_out, 0, v);
827
828 // TODO: This is incorrect. We should not use a very large number to ensure
829 // that this statement is executed last.
830 isl_int_set_si(v, 200000000);
831 isl_constraint_set_constant(c, v);
832
833 bmap = isl_basic_map_add_constraint(bmap, c);
834 isl_int_clear(v);
835 Scattering = isl_map_from_basic_map(bmap);
836
837 // Build memory accesses, use SetVector to keep the order of memory accesses
838 // and prevent the same memory access inserted more than once.
839 SetVector<const Value*> BaseAddressSet;
840
841 for (Scop::const_iterator SI = Parent.begin(), SE = Parent.end(); SI != SE;
842 ++SI) {
843 ScopStmt *Stmt = *SI;
844
845 for (MemoryAccessVec::const_iterator I = Stmt->memacc_begin(),
846 E = Stmt->memacc_end(); I != E; ++I)
847 BaseAddressSet.insert((*I)->getBaseAddr());
848 }
849
850 for (SetVector<const Value*>::iterator BI = BaseAddressSet.begin(),
851 BE = BaseAddressSet.end(); BI != BE; ++BI)
852 MemAccs.push_back(new MemoryAccess(*BI, this));
853
854 IsReduction = false;
855}
856
857std::string ScopStmt::getDomainStr() const {
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +0000858 isl_set *domain = getDomain();
859 std::string string = stringFromIslObj(domain);
860 isl_set_free(domain);
861 return string;
Tobias Grosser75805372011-04-29 06:27:02 +0000862}
863
864std::string ScopStmt::getScatteringStr() const {
865 return stringFromIslObj(getScattering());
866}
867
868unsigned ScopStmt::getNumParams() const {
869 return Parent.getNumParams();
870}
871
872unsigned ScopStmt::getNumIterators() const {
873 // The final read has one dimension with one element.
874 if (!BB)
875 return 1;
876
877 return IVS.size();
878}
879
880unsigned ScopStmt::getNumScattering() const {
881 return isl_map_dim(Scattering, isl_dim_out);
882}
883
884const char *ScopStmt::getBaseName() const { return BaseName.c_str(); }
885
886const PHINode *ScopStmt::getInductionVariableForDimension(unsigned Dimension)
887 const {
Hongbin Zheng27f3afb2011-04-30 03:26:51 +0000888 return IVS[Dimension].first;
889}
890
891const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const {
892 return IVS[Dimension].second;
Tobias Grosser75805372011-04-29 06:27:02 +0000893}
894
895const SCEVAddRecExpr *ScopStmt::getSCEVForDimension(unsigned Dimension)
896 const {
Hongbin Zheng27f3afb2011-04-30 03:26:51 +0000897 PHINode *PN =
898 const_cast<PHINode*>(getInductionVariableForDimension(Dimension));
Tobias Grosser75805372011-04-29 06:27:02 +0000899 return cast<SCEVAddRecExpr>(getParent()->getSE()->getSCEV(PN));
900}
901
902isl_ctx *ScopStmt::getIslContext() {
903 return Parent.getCtx();
904}
905
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +0000906isl_set *ScopStmt::getDomain() const {
907 return isl_set_copy(Domain);
908}
909
Tobias Grosser75805372011-04-29 06:27:02 +0000910ScopStmt::~ScopStmt() {
911 while (!MemAccs.empty()) {
912 delete MemAccs.back();
913 MemAccs.pop_back();
914 }
915
916 isl_set_free(Domain);
917 isl_map_free(Scattering);
918}
919
920void ScopStmt::print(raw_ostream &OS) const {
921 OS << "\t" << getBaseName() << "\n";
922
923 OS.indent(12) << "Domain :=\n";
924
925 if (Domain) {
926 OS.indent(16) << getDomainStr() << ";\n";
927 } else
928 OS.indent(16) << "n/a\n";
929
930 OS.indent(12) << "Scattering :=\n";
931
932 if (Domain) {
933 OS.indent(16) << getScatteringStr() << ";\n";
934 } else
935 OS.indent(16) << "n/a\n";
936
937 for (MemoryAccessVec::const_iterator I = MemAccs.begin(), E = MemAccs.end();
938 I != E; ++I)
939 (*I)->print(OS);
940}
941
942void ScopStmt::dump() const { print(dbgs()); }
943
944//===----------------------------------------------------------------------===//
945/// Scop class implement
946Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution)
947 : SE(&ScalarEvolution), R(tempScop.getMaxRegion()),
948 MaxLoopDepth(tempScop.getMaxLoopDepth()) {
949 isl_ctx *ctx = isl_ctx_alloc();
950
951 ParamSetType &Params = tempScop.getParamSet();
952 Parameters.insert(Parameters.begin(), Params.begin(), Params.end());
953
954 isl_dim *dim = isl_dim_set_alloc(ctx, getNumParams(), 0);
955
956 // TODO: Insert relations between parameters.
957 // TODO: Insert constraints on parameters.
958 Context = isl_set_universe (dim);
959
960 SmallVector<Loop*, 8> NestLoops;
961 SmallVector<unsigned, 8> Scatter;
962
963 Scatter.assign(MaxLoopDepth + 1, 0);
964
965 // Build the iteration domain, access functions and scattering functions
966 // traversing the region tree.
967 buildScop(tempScop, getRegion(), NestLoops, Scatter, LI);
968 Stmts.push_back(new ScopStmt(*this, Scatter));
969
970 assert(NestLoops.empty() && "NestLoops not empty at top level!");
971}
972
973Scop::~Scop() {
974 isl_set_free(Context);
975
976 // Free the statements;
977 for (iterator I = begin(), E = end(); I != E; ++I)
978 delete *I;
979
980 // Do we need a singleton to manage this?
981 //isl_ctx_free(ctx);
982}
983
984std::string Scop::getContextStr() const {
985 return stringFromIslObj(getContext());
986}
987
988std::string Scop::getNameStr() const {
989 std::string ExitName, EntryName;
990 raw_string_ostream ExitStr(ExitName);
991 raw_string_ostream EntryStr(EntryName);
992
993 WriteAsOperand(EntryStr, R.getEntry(), false);
994 EntryStr.str();
995
996 if (R.getExit()) {
997 WriteAsOperand(ExitStr, R.getExit(), false);
998 ExitStr.str();
999 } else
1000 ExitName = "FunctionExit";
1001
1002 return EntryName + "---" + ExitName;
1003}
1004
1005void Scop::printContext(raw_ostream &OS) const {
1006 OS << "Context:\n";
1007
1008 if (!Context) {
1009 OS.indent(4) << "n/a\n\n";
1010 return;
1011 }
1012
1013 OS.indent(4) << getContextStr() << "\n";
1014}
1015
1016void Scop::printStatements(raw_ostream &OS) const {
1017 OS << "Statements {\n";
1018
1019 for (const_iterator SI = begin(), SE = end();SI != SE; ++SI)
1020 OS.indent(4) << (**SI);
1021
1022 OS.indent(4) << "}\n";
1023}
1024
1025
1026void Scop::print(raw_ostream &OS) const {
1027 printContext(OS.indent(4));
1028 printStatements(OS.indent(4));
1029}
1030
1031void Scop::dump() const { print(dbgs()); }
1032
1033isl_ctx *Scop::getCtx() const { return isl_set_get_ctx(Context); }
1034
1035ScalarEvolution *Scop::getSE() const { return SE; }
1036
1037bool Scop::isTrivialBB(BasicBlock *BB, TempScop &tempScop) {
1038 if (tempScop.getAccessFunctions(BB))
1039 return false;
1040
1041 return true;
1042}
1043
1044void Scop::buildScop(TempScop &tempScop,
1045 const Region &CurRegion,
1046 SmallVectorImpl<Loop*> &NestLoops,
1047 SmallVectorImpl<unsigned> &Scatter,
1048 LoopInfo &LI) {
1049 Loop *L = castToLoop(CurRegion, LI);
1050
1051 if (L)
1052 NestLoops.push_back(L);
1053
1054 unsigned loopDepth = NestLoops.size();
1055 assert(Scatter.size() > loopDepth && "Scatter not big enough!");
1056
1057 for (Region::const_element_iterator I = CurRegion.element_begin(),
1058 E = CurRegion.element_end(); I != E; ++I)
1059 if (I->isSubRegion())
1060 buildScop(tempScop, *(I->getNodeAs<Region>()), NestLoops, Scatter, LI);
1061 else {
1062 BasicBlock *BB = I->getNodeAs<BasicBlock>();
1063
1064 if (isTrivialBB(BB, tempScop))
1065 continue;
1066
1067 Stmts.push_back(new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops,
1068 Scatter));
1069
1070 // Increasing the Scattering function is OK for the moment, because
1071 // we are using a depth first iterator and the program is well structured.
1072 ++Scatter[loopDepth];
1073 }
1074
1075 if (!L)
1076 return;
1077
1078 // Exiting a loop region.
1079 Scatter[loopDepth] = 0;
1080 NestLoops.pop_back();
1081 ++Scatter[loopDepth-1];
1082}
1083
1084//===----------------------------------------------------------------------===//
1085
1086void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
1087 AU.addRequired<LoopInfo>();
1088 AU.addRequired<RegionInfo>();
1089 AU.addRequired<ScalarEvolution>();
1090 AU.addRequired<TempScopInfo>();
1091 AU.setPreservesAll();
1092}
1093
1094bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
1095 LoopInfo &LI = getAnalysis<LoopInfo>();
1096 ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
1097
1098 TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
1099
1100 // This region is no Scop.
1101 if (!tempScop) {
1102 scop = 0;
1103 return false;
1104 }
1105
1106 // Statistics.
1107 ++ScopFound;
1108 if (tempScop->getMaxLoopDepth() > 0) ++RichScopFound;
1109
1110 scop = new Scop(*tempScop, LI, SE);
1111
1112 return false;
1113}
1114
1115char ScopInfo::ID = 0;
1116
1117
1118static RegisterPass<ScopInfo>
1119X("polly-scops", "Polly - Create polyhedral description of Scops");
1120
1121Pass *polly::createScopInfoPass() {
1122 return new ScopInfo();
1123}