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