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