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