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