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/Options.h" 24 #include "polly/Support/GICHelper.h" 25 #include "polly/Support/SCEVValidator.h" 26 #include "polly/Support/ScopHelper.h" 27 #include "polly/TempScopInfo.h" 28 #include "llvm/ADT/SetVector.h" 29 #include "llvm/ADT/Statistic.h" 30 #include "llvm/ADT/StringExtras.h" 31 #include "llvm/Analysis/LoopInfo.h" 32 #include "llvm/Analysis/RegionIterator.h" 33 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 34 #include "llvm/Support/Debug.h" 35 36 #include "isl/constraint.h" 37 #include "isl/set.h" 38 #include "isl/map.h" 39 #include "isl/union_map.h" 40 #include "isl/aff.h" 41 #include "isl/printer.h" 42 #include "isl/local_space.h" 43 #include "isl/options.h" 44 #include "isl/val.h" 45 46 #include <sstream> 47 #include <string> 48 #include <vector> 49 50 using namespace llvm; 51 using namespace polly; 52 53 #define DEBUG_TYPE "polly-scops" 54 55 STATISTIC(ScopFound, "Number of valid Scops"); 56 STATISTIC(RichScopFound, "Number of Scops containing a loop"); 57 58 // Multiplicative reductions can be disabled seperately as these kind of 59 // operations can overflow easily. Additive reductions and bit operations 60 // are in contrast pretty stable. 61 static cl::opt<bool> DisableMultiplicativeReductions( 62 "polly-disable-multiplicative-reductions", 63 cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::ZeroOrMore, 64 cl::init(false), cl::cat(PollyCategory)); 65 66 /// Translate a 'const SCEV *' expression in an isl_pw_aff. 67 struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff *> { 68 public: 69 /// @brief Translate a 'const SCEV *' to an isl_pw_aff. 70 /// 71 /// @param Stmt The location at which the scalar evolution expression 72 /// is evaluated. 73 /// @param Expr The expression that is translated. 74 static __isl_give isl_pw_aff *getPwAff(ScopStmt *Stmt, const SCEV *Expr); 75 76 private: 77 isl_ctx *Ctx; 78 int NbLoopSpaces; 79 const Scop *S; 80 81 SCEVAffinator(const ScopStmt *Stmt); 82 int getLoopDepth(const Loop *L); 83 84 __isl_give isl_pw_aff *visit(const SCEV *Expr); 85 __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Expr); 86 __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr *Expr); 87 __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr); 88 __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr *Expr); 89 __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr *Expr); 90 __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr *Expr); 91 __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr *Expr); 92 __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr *Expr); 93 __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr *Expr); 94 __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr *Expr); 95 __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown *Expr); 96 97 friend struct SCEVVisitor<SCEVAffinator, isl_pw_aff *>; 98 }; 99 100 SCEVAffinator::SCEVAffinator(const ScopStmt *Stmt) 101 : Ctx(Stmt->getIslCtx()), NbLoopSpaces(Stmt->getNumIterators()), 102 S(Stmt->getParent()) {} 103 104 __isl_give isl_pw_aff *SCEVAffinator::getPwAff(ScopStmt *Stmt, 105 const SCEV *Scev) { 106 Scop *S = Stmt->getParent(); 107 const Region *Reg = &S->getRegion(); 108 109 S->addParams(getParamsInAffineExpr(Reg, Scev, *S->getSE())); 110 111 SCEVAffinator Affinator(Stmt); 112 return Affinator.visit(Scev); 113 } 114 115 __isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) { 116 // In case the scev is a valid parameter, we do not further analyze this 117 // expression, but create a new parameter in the isl_pw_aff. This allows us 118 // to treat subexpressions that we cannot translate into an piecewise affine 119 // expression, as constant parameters of the piecewise affine expression. 120 if (isl_id *Id = S->getIdForParam(Expr)) { 121 isl_space *Space = isl_space_set_alloc(Ctx, 1, NbLoopSpaces); 122 Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id); 123 124 isl_set *Domain = isl_set_universe(isl_space_copy(Space)); 125 isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space)); 126 Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1); 127 128 return isl_pw_aff_alloc(Domain, Affine); 129 } 130 131 return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr); 132 } 133 134 __isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) { 135 ConstantInt *Value = Expr->getValue(); 136 isl_val *v; 137 138 // LLVM does not define if an integer value is interpreted as a signed or 139 // unsigned value. Hence, without further information, it is unknown how 140 // this value needs to be converted to GMP. At the moment, we only support 141 // signed operations. So we just interpret it as signed. Later, there are 142 // two options: 143 // 144 // 1. We always interpret any value as signed and convert the values on 145 // demand. 146 // 2. We pass down the signedness of the calculation and use it to interpret 147 // this constant correctly. 148 v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true); 149 150 isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces); 151 isl_local_space *ls = isl_local_space_from_space(isl_space_copy(Space)); 152 isl_aff *Affine = isl_aff_zero_on_domain(ls); 153 isl_set *Domain = isl_set_universe(Space); 154 155 Affine = isl_aff_add_constant_val(Affine, v); 156 157 return isl_pw_aff_alloc(Domain, Affine); 158 } 159 160 __isl_give isl_pw_aff * 161 SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) { 162 llvm_unreachable("SCEVTruncateExpr not yet supported"); 163 } 164 165 __isl_give isl_pw_aff * 166 SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { 167 llvm_unreachable("SCEVZeroExtendExpr not yet supported"); 168 } 169 170 __isl_give isl_pw_aff * 171 SCEVAffinator::visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { 172 // Assuming the value is signed, a sign extension is basically a noop. 173 // TODO: Reconsider this as soon as we support unsigned values. 174 return visit(Expr->getOperand()); 175 } 176 177 __isl_give isl_pw_aff *SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) { 178 isl_pw_aff *Sum = visit(Expr->getOperand(0)); 179 180 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { 181 isl_pw_aff *NextSummand = visit(Expr->getOperand(i)); 182 Sum = isl_pw_aff_add(Sum, NextSummand); 183 } 184 185 // TODO: Check for NSW and NUW. 186 187 return Sum; 188 } 189 190 __isl_give isl_pw_aff *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) { 191 isl_pw_aff *Product = visit(Expr->getOperand(0)); 192 193 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { 194 isl_pw_aff *NextOperand = visit(Expr->getOperand(i)); 195 196 if (!isl_pw_aff_is_cst(Product) && !isl_pw_aff_is_cst(NextOperand)) { 197 isl_pw_aff_free(Product); 198 isl_pw_aff_free(NextOperand); 199 return nullptr; 200 } 201 202 Product = isl_pw_aff_mul(Product, NextOperand); 203 } 204 205 // TODO: Check for NSW and NUW. 206 return Product; 207 } 208 209 __isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) { 210 llvm_unreachable("SCEVUDivExpr not yet supported"); 211 } 212 213 __isl_give isl_pw_aff * 214 SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) { 215 assert(Expr->isAffine() && "Only affine AddRecurrences allowed"); 216 217 // Directly generate isl_pw_aff for Expr if 'start' is zero. 218 if (Expr->getStart()->isZero()) { 219 assert(S->getRegion().contains(Expr->getLoop()) && 220 "Scop does not contain the loop referenced in this AddRec"); 221 222 isl_pw_aff *Start = visit(Expr->getStart()); 223 isl_pw_aff *Step = visit(Expr->getOperand(1)); 224 isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces); 225 isl_local_space *LocalSpace = isl_local_space_from_space(Space); 226 227 int loopDimension = getLoopDepth(Expr->getLoop()); 228 229 isl_aff *LAff = isl_aff_set_coefficient_si( 230 isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1); 231 isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff); 232 233 // TODO: Do we need to check for NSW and NUW? 234 return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff)); 235 } 236 237 // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}' 238 // if 'start' is not zero. 239 ScalarEvolution &SE = *S->getSE(); 240 const SCEV *ZeroStartExpr = SE.getAddRecExpr( 241 SE.getConstant(Expr->getStart()->getType(), 0), 242 Expr->getStepRecurrence(SE), Expr->getLoop(), SCEV::FlagAnyWrap); 243 244 isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr); 245 isl_pw_aff *Start = visit(Expr->getStart()); 246 247 return isl_pw_aff_add(ZeroStartResult, Start); 248 } 249 250 __isl_give isl_pw_aff *SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) { 251 isl_pw_aff *Max = visit(Expr->getOperand(0)); 252 253 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { 254 isl_pw_aff *NextOperand = visit(Expr->getOperand(i)); 255 Max = isl_pw_aff_max(Max, NextOperand); 256 } 257 258 return Max; 259 } 260 261 __isl_give isl_pw_aff *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) { 262 llvm_unreachable("SCEVUMaxExpr not yet supported"); 263 } 264 265 __isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) { 266 llvm_unreachable("Unknowns are always parameters"); 267 } 268 269 int SCEVAffinator::getLoopDepth(const Loop *L) { 270 Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L)); 271 assert(outerLoop && "Scop does not contain this loop"); 272 return L->getLoopDepth() - outerLoop->getLoopDepth(); 273 } 274 275 const std::string 276 MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) { 277 switch (RT) { 278 case MemoryAccess::RT_NONE: 279 llvm_unreachable("Requested a reduction operator string for a memory " 280 "access which isn't a reduction"); 281 case MemoryAccess::RT_ADD: 282 return "+"; 283 case MemoryAccess::RT_MUL: 284 return "*"; 285 case MemoryAccess::RT_BOR: 286 return "|"; 287 case MemoryAccess::RT_BXOR: 288 return "^"; 289 case MemoryAccess::RT_BAND: 290 return "&"; 291 } 292 llvm_unreachable("Unknown reduction type"); 293 return ""; 294 } 295 296 /// @brief Return the reduction type for a given binary operator 297 static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp, 298 const Instruction *Load) { 299 if (!BinOp) 300 return MemoryAccess::RT_NONE; 301 switch (BinOp->getOpcode()) { 302 case Instruction::FAdd: 303 if (!BinOp->hasUnsafeAlgebra()) 304 return MemoryAccess::RT_NONE; 305 // Fall through 306 case Instruction::Add: 307 return MemoryAccess::RT_ADD; 308 case Instruction::Or: 309 return MemoryAccess::RT_BOR; 310 case Instruction::Xor: 311 return MemoryAccess::RT_BXOR; 312 case Instruction::And: 313 return MemoryAccess::RT_BAND; 314 case Instruction::FMul: 315 if (!BinOp->hasUnsafeAlgebra()) 316 return MemoryAccess::RT_NONE; 317 // Fall through 318 case Instruction::Mul: 319 if (DisableMultiplicativeReductions) 320 return MemoryAccess::RT_NONE; 321 return MemoryAccess::RT_MUL; 322 default: 323 return MemoryAccess::RT_NONE; 324 } 325 } 326 //===----------------------------------------------------------------------===// 327 328 MemoryAccess::~MemoryAccess() { 329 isl_map_free(AccessRelation); 330 isl_map_free(newAccessRelation); 331 } 332 333 isl_id *MemoryAccess::getArrayId() const { 334 return isl_map_get_tuple_id(AccessRelation, isl_dim_out); 335 } 336 337 isl_map *MemoryAccess::getAccessRelation() const { 338 return isl_map_copy(AccessRelation); 339 } 340 341 std::string MemoryAccess::getAccessRelationStr() const { 342 return stringFromIslObj(AccessRelation); 343 } 344 345 __isl_give isl_space *MemoryAccess::getAccessRelationSpace() const { 346 return isl_map_get_space(AccessRelation); 347 } 348 349 isl_map *MemoryAccess::getNewAccessRelation() const { 350 return isl_map_copy(newAccessRelation); 351 } 352 353 isl_basic_map *MemoryAccess::createBasicAccessMap(ScopStmt *Statement) { 354 isl_space *Space = isl_space_set_alloc(Statement->getIslCtx(), 0, 1); 355 Space = isl_space_align_params(Space, Statement->getDomainSpace()); 356 357 return isl_basic_map_from_domain_and_range( 358 isl_basic_set_universe(Statement->getDomainSpace()), 359 isl_basic_set_universe(Space)); 360 } 361 362 // Formalize no out-of-bound access assumption 363 // 364 // When delinearizing array accesses we optimistically assume that the 365 // delinearized accesses do not access out of bound locations (the subscript 366 // expression of each array evaluates for each statement instance that is 367 // executed to a value that is larger than zero and strictly smaller than the 368 // size of the corresponding dimension). The only exception is the outermost 369 // dimension for which we do not need to assume any upper bound. At this point 370 // we formalize this assumption to ensure that at code generation time the 371 // relevant run-time checks can be generated. 372 // 373 // To find the set of constraints necessary to avoid out of bound accesses, we 374 // first build the set of data locations that are not within array bounds. We 375 // then apply the reverse access relation to obtain the set of iterations that 376 // may contain invalid accesses and reduce this set of iterations to the ones 377 // that are actually executed by intersecting them with the domain of the 378 // statement. If we now project out all loop dimensions, we obtain a set of 379 // parameters that may cause statement instances to be executed that may 380 // possibly yield out of bound memory accesses. The complement of these 381 // constraints is the set of constraints that needs to be assumed to ensure such 382 // statement instances are never executed. 383 void MemoryAccess::assumeNoOutOfBound(const IRAccess &Access) { 384 isl_space *Space = isl_space_range(getAccessRelationSpace()); 385 isl_set *Outside = isl_set_empty(isl_space_copy(Space)); 386 for (int i = 1, Size = Access.Subscripts.size(); i < Size; ++i) { 387 isl_local_space *LS = isl_local_space_from_space(isl_space_copy(Space)); 388 isl_pw_aff *Var = 389 isl_pw_aff_var_on_domain(isl_local_space_copy(LS), isl_dim_set, i); 390 isl_pw_aff *Zero = isl_pw_aff_zero_on_domain(LS); 391 392 isl_set *DimOutside; 393 394 DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero); 395 isl_pw_aff *SizeE = SCEVAffinator::getPwAff(Statement, Access.Sizes[i - 1]); 396 397 SizeE = isl_pw_aff_drop_dims(SizeE, isl_dim_in, 0, 398 Statement->getNumIterators()); 399 SizeE = isl_pw_aff_add_dims(SizeE, isl_dim_in, 400 isl_space_dim(Space, isl_dim_set)); 401 SizeE = isl_pw_aff_set_tuple_id(SizeE, isl_dim_in, 402 isl_space_get_tuple_id(Space, isl_dim_set)); 403 404 DimOutside = isl_set_union(DimOutside, isl_pw_aff_le_set(SizeE, Var)); 405 406 Outside = isl_set_union(Outside, DimOutside); 407 } 408 409 Outside = isl_set_apply(Outside, isl_map_reverse(getAccessRelation())); 410 Outside = isl_set_intersect(Outside, Statement->getDomain()); 411 Outside = isl_set_params(Outside); 412 Outside = isl_set_complement(Outside); 413 Statement->getParent()->addAssumption(Outside); 414 isl_space_free(Space); 415 } 416 417 MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst, 418 ScopStmt *Statement) 419 : Statement(Statement), Inst(AccInst), newAccessRelation(nullptr) { 420 421 isl_ctx *Ctx = Statement->getIslCtx(); 422 BaseAddr = Access.getBase(); 423 BaseName = getIslCompatibleName("MemRef_", getBaseAddr(), ""); 424 isl_id *BaseAddrId = isl_id_alloc(Ctx, getBaseName().c_str(), nullptr); 425 426 if (!Access.isAffine()) { 427 // We overapproximate non-affine accesses with a possible access to the 428 // whole array. For read accesses it does not make a difference, if an 429 // access must or may happen. However, for write accesses it is important to 430 // differentiate between writes that must happen and writes that may happen. 431 AccessRelation = isl_map_from_basic_map(createBasicAccessMap(Statement)); 432 AccessRelation = 433 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId); 434 Type = Access.isRead() ? READ : MAY_WRITE; 435 return; 436 } 437 438 Type = Access.isRead() ? READ : MUST_WRITE; 439 440 isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0); 441 AccessRelation = isl_map_universe(Space); 442 443 for (int i = 0, Size = Access.Subscripts.size(); i < Size; ++i) { 444 isl_pw_aff *Affine = 445 SCEVAffinator::getPwAff(Statement, Access.Subscripts[i]); 446 447 if (Size == 1) { 448 // For the non delinearized arrays, divide the access function of the last 449 // subscript by the size of the elements in the array. 450 // 451 // A stride one array access in C expressed as A[i] is expressed in 452 // LLVM-IR as something like A[i * elementsize]. This hides the fact that 453 // two subsequent values of 'i' index two values that are stored next to 454 // each other in memory. By this division we make this characteristic 455 // obvious again. 456 isl_val *v = isl_val_int_from_si(Ctx, Access.getElemSizeInBytes()); 457 Affine = isl_pw_aff_scale_down_val(Affine, v); 458 } 459 460 isl_map *SubscriptMap = isl_map_from_pw_aff(Affine); 461 462 AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap); 463 } 464 465 Space = Statement->getDomainSpace(); 466 AccessRelation = isl_map_set_tuple_id( 467 AccessRelation, isl_dim_in, isl_space_get_tuple_id(Space, isl_dim_set)); 468 AccessRelation = 469 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId); 470 471 assumeNoOutOfBound(Access); 472 isl_space_free(Space); 473 } 474 475 void MemoryAccess::realignParams() { 476 isl_space *ParamSpace = Statement->getParent()->getParamSpace(); 477 AccessRelation = isl_map_align_params(AccessRelation, ParamSpace); 478 } 479 480 const std::string MemoryAccess::getReductionOperatorStr() const { 481 return MemoryAccess::getReductionOperatorStr(getReductionType()); 482 } 483 484 raw_ostream &polly::operator<<(raw_ostream &OS, 485 MemoryAccess::ReductionType RT) { 486 if (RT == MemoryAccess::RT_NONE) 487 OS << "NONE"; 488 else 489 OS << MemoryAccess::getReductionOperatorStr(RT); 490 return OS; 491 } 492 493 void MemoryAccess::print(raw_ostream &OS) const { 494 switch (Type) { 495 case READ: 496 OS.indent(12) << "ReadAccess :=\t"; 497 break; 498 case MUST_WRITE: 499 OS.indent(12) << "MustWriteAccess :=\t"; 500 break; 501 case MAY_WRITE: 502 OS.indent(12) << "MayWriteAccess :=\t"; 503 break; 504 } 505 OS << "[Reduction Type: " << getReductionType() << "]\n"; 506 OS.indent(16) << getAccessRelationStr() << ";\n"; 507 } 508 509 void MemoryAccess::dump() const { print(errs()); } 510 511 // Create a map in the size of the provided set domain, that maps from the 512 // one element of the provided set domain to another element of the provided 513 // set domain. 514 // The mapping is limited to all points that are equal in all but the last 515 // dimension and for which the last dimension of the input is strict smaller 516 // than the last dimension of the output. 517 // 518 // getEqualAndLarger(set[i0, i1, ..., iX]): 519 // 520 // set[i0, i1, ..., iX] -> set[o0, o1, ..., oX] 521 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX 522 // 523 static isl_map *getEqualAndLarger(isl_space *setDomain) { 524 isl_space *Space = isl_space_map_from_set(setDomain); 525 isl_map *Map = isl_map_universe(isl_space_copy(Space)); 526 isl_local_space *MapLocalSpace = isl_local_space_from_space(Space); 527 unsigned lastDimension = isl_map_dim(Map, isl_dim_in) - 1; 528 529 // Set all but the last dimension to be equal for the input and output 530 // 531 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX] 532 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1) 533 for (unsigned i = 0; i < lastDimension; ++i) 534 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); 535 536 // Set the last dimension of the input to be strict smaller than the 537 // last dimension of the output. 538 // 539 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX 540 // 541 isl_val *v; 542 isl_ctx *Ctx = isl_map_get_ctx(Map); 543 isl_constraint *c = isl_inequality_alloc(isl_local_space_copy(MapLocalSpace)); 544 v = isl_val_int_from_si(Ctx, -1); 545 c = isl_constraint_set_coefficient_val(c, isl_dim_in, lastDimension, v); 546 v = isl_val_int_from_si(Ctx, 1); 547 c = isl_constraint_set_coefficient_val(c, isl_dim_out, lastDimension, v); 548 v = isl_val_int_from_si(Ctx, -1); 549 c = isl_constraint_set_constant_val(c, v); 550 551 Map = isl_map_add_constraint(Map, c); 552 553 isl_local_space_free(MapLocalSpace); 554 return Map; 555 } 556 557 isl_set *MemoryAccess::getStride(__isl_take const isl_map *Schedule) const { 558 isl_map *S = const_cast<isl_map *>(Schedule); 559 isl_map *AccessRelation = getAccessRelation(); 560 isl_space *Space = isl_space_range(isl_map_get_space(S)); 561 isl_map *NextScatt = getEqualAndLarger(Space); 562 563 S = isl_map_reverse(S); 564 NextScatt = isl_map_lexmin(NextScatt); 565 566 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S)); 567 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation)); 568 NextScatt = isl_map_apply_domain(NextScatt, S); 569 NextScatt = isl_map_apply_domain(NextScatt, AccessRelation); 570 571 isl_set *Deltas = isl_map_deltas(NextScatt); 572 return Deltas; 573 } 574 575 bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule, 576 int StrideWidth) const { 577 isl_set *Stride, *StrideX; 578 bool IsStrideX; 579 580 Stride = getStride(Schedule); 581 StrideX = isl_set_universe(isl_set_get_space(Stride)); 582 StrideX = isl_set_fix_si(StrideX, isl_dim_set, 0, StrideWidth); 583 IsStrideX = isl_set_is_equal(Stride, StrideX); 584 585 isl_set_free(StrideX); 586 isl_set_free(Stride); 587 588 return IsStrideX; 589 } 590 591 bool MemoryAccess::isStrideZero(const isl_map *Schedule) const { 592 return isStrideX(Schedule, 0); 593 } 594 595 bool MemoryAccess::isScalar() const { 596 return isl_map_n_out(AccessRelation) == 0; 597 } 598 599 bool MemoryAccess::isStrideOne(const isl_map *Schedule) const { 600 return isStrideX(Schedule, 1); 601 } 602 603 void MemoryAccess::setNewAccessRelation(isl_map *newAccess) { 604 isl_map_free(newAccessRelation); 605 newAccessRelation = newAccess; 606 } 607 608 //===----------------------------------------------------------------------===// 609 610 isl_map *ScopStmt::getScattering() const { return isl_map_copy(Scattering); } 611 612 void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) { 613 assert(isl_set_is_subset(NewDomain, Domain) && 614 "New domain is not a subset of old domain!"); 615 isl_set_free(Domain); 616 Domain = NewDomain; 617 Scattering = isl_map_intersect_domain(Scattering, isl_set_copy(Domain)); 618 } 619 620 void ScopStmt::setScattering(isl_map *NewScattering) { 621 assert(NewScattering && "New scattering is nullptr"); 622 isl_map_free(Scattering); 623 Scattering = NewScattering; 624 } 625 626 void ScopStmt::buildScattering(SmallVectorImpl<unsigned> &Scatter) { 627 unsigned NbIterators = getNumIterators(); 628 unsigned NbScatteringDims = Parent.getMaxLoopDepth() * 2 + 1; 629 630 isl_space *Space = isl_space_set_alloc(getIslCtx(), 0, NbScatteringDims); 631 Space = isl_space_set_tuple_name(Space, isl_dim_out, "scattering"); 632 633 Scattering = isl_map_from_domain_and_range(isl_set_universe(getDomainSpace()), 634 isl_set_universe(Space)); 635 636 // Loop dimensions. 637 for (unsigned i = 0; i < NbIterators; ++i) 638 Scattering = 639 isl_map_equate(Scattering, isl_dim_out, 2 * i + 1, isl_dim_in, i); 640 641 // Constant dimensions 642 for (unsigned i = 0; i < NbIterators + 1; ++i) 643 Scattering = isl_map_fix_si(Scattering, isl_dim_out, 2 * i, Scatter[i]); 644 645 // Fill scattering dimensions. 646 for (unsigned i = 2 * NbIterators + 1; i < NbScatteringDims; ++i) 647 Scattering = isl_map_fix_si(Scattering, isl_dim_out, i, 0); 648 649 Scattering = isl_map_align_params(Scattering, Parent.getParamSpace()); 650 } 651 652 void ScopStmt::buildAccesses(TempScop &tempScop, const Region &CurRegion) { 653 for (auto &&Access : *tempScop.getAccessFunctions(BB)) { 654 MemAccs.push_back(new MemoryAccess(Access.first, Access.second, this)); 655 656 // We do not track locations for scalar memory accesses at the moment. 657 // 658 // We do not have a use for this information at the moment. If we need this 659 // at some point, the "instruction -> access" mapping needs to be enhanced 660 // as a single instruction could then possibly perform multiple accesses. 661 if (!Access.first.isScalar()) { 662 assert(!InstructionToAccess.count(Access.second) && 663 "Unexpected 1-to-N mapping on instruction to access map!"); 664 InstructionToAccess[Access.second] = MemAccs.back(); 665 } 666 } 667 } 668 669 void ScopStmt::realignParams() { 670 for (MemoryAccess *MA : *this) 671 MA->realignParams(); 672 673 Domain = isl_set_align_params(Domain, Parent.getParamSpace()); 674 Scattering = isl_map_align_params(Scattering, Parent.getParamSpace()); 675 } 676 677 __isl_give isl_set *ScopStmt::buildConditionSet(const Comparison &Comp) { 678 isl_pw_aff *L = SCEVAffinator::getPwAff(this, Comp.getLHS()); 679 isl_pw_aff *R = SCEVAffinator::getPwAff(this, Comp.getRHS()); 680 681 switch (Comp.getPred()) { 682 case ICmpInst::ICMP_EQ: 683 return isl_pw_aff_eq_set(L, R); 684 case ICmpInst::ICMP_NE: 685 return isl_pw_aff_ne_set(L, R); 686 case ICmpInst::ICMP_SLT: 687 return isl_pw_aff_lt_set(L, R); 688 case ICmpInst::ICMP_SLE: 689 return isl_pw_aff_le_set(L, R); 690 case ICmpInst::ICMP_SGT: 691 return isl_pw_aff_gt_set(L, R); 692 case ICmpInst::ICMP_SGE: 693 return isl_pw_aff_ge_set(L, R); 694 case ICmpInst::ICMP_ULT: 695 case ICmpInst::ICMP_UGT: 696 case ICmpInst::ICMP_ULE: 697 case ICmpInst::ICMP_UGE: 698 llvm_unreachable("Unsigned comparisons not yet supported"); 699 default: 700 llvm_unreachable("Non integer predicate not supported"); 701 } 702 } 703 704 __isl_give isl_set *ScopStmt::addLoopBoundsToDomain(__isl_take isl_set *Domain, 705 TempScop &tempScop) { 706 isl_space *Space; 707 isl_local_space *LocalSpace; 708 709 Space = isl_set_get_space(Domain); 710 LocalSpace = isl_local_space_from_space(Space); 711 712 for (int i = 0, e = getNumIterators(); i != e; ++i) { 713 isl_aff *Zero = isl_aff_zero_on_domain(isl_local_space_copy(LocalSpace)); 714 isl_pw_aff *IV = 715 isl_pw_aff_from_aff(isl_aff_set_coefficient_si(Zero, isl_dim_in, i, 1)); 716 717 // 0 <= IV. 718 isl_set *LowerBound = isl_pw_aff_nonneg_set(isl_pw_aff_copy(IV)); 719 Domain = isl_set_intersect(Domain, LowerBound); 720 721 // IV <= LatchExecutions. 722 const Loop *L = getLoopForDimension(i); 723 const SCEV *LatchExecutions = tempScop.getLoopBound(L); 724 isl_pw_aff *UpperBound = SCEVAffinator::getPwAff(this, LatchExecutions); 725 isl_set *UpperBoundSet = isl_pw_aff_le_set(IV, UpperBound); 726 Domain = isl_set_intersect(Domain, UpperBoundSet); 727 } 728 729 isl_local_space_free(LocalSpace); 730 return Domain; 731 } 732 733 __isl_give isl_set *ScopStmt::addConditionsToDomain(__isl_take isl_set *Domain, 734 TempScop &tempScop, 735 const Region &CurRegion) { 736 const Region *TopRegion = tempScop.getMaxRegion().getParent(), 737 *CurrentRegion = &CurRegion; 738 const BasicBlock *BranchingBB = BB; 739 740 do { 741 if (BranchingBB != CurrentRegion->getEntry()) { 742 if (const BBCond *Condition = tempScop.getBBCond(BranchingBB)) 743 for (const auto &C : *Condition) { 744 isl_set *ConditionSet = buildConditionSet(C); 745 Domain = isl_set_intersect(Domain, ConditionSet); 746 } 747 } 748 BranchingBB = CurrentRegion->getEntry(); 749 CurrentRegion = CurrentRegion->getParent(); 750 } while (TopRegion != CurrentRegion); 751 752 return Domain; 753 } 754 755 __isl_give isl_set *ScopStmt::buildDomain(TempScop &tempScop, 756 const Region &CurRegion) { 757 isl_space *Space; 758 isl_set *Domain; 759 isl_id *Id; 760 761 Space = isl_space_set_alloc(getIslCtx(), 0, getNumIterators()); 762 763 Id = isl_id_alloc(getIslCtx(), getBaseName(), this); 764 765 Domain = isl_set_universe(Space); 766 Domain = addLoopBoundsToDomain(Domain, tempScop); 767 Domain = addConditionsToDomain(Domain, tempScop, CurRegion); 768 Domain = isl_set_set_tuple_id(Domain, Id); 769 770 return Domain; 771 } 772 773 ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion, 774 BasicBlock &bb, SmallVectorImpl<Loop *> &Nest, 775 SmallVectorImpl<unsigned> &Scatter) 776 : Parent(parent), BB(&bb), IVS(Nest.size()), NestLoops(Nest.size()) { 777 // Setup the induction variables. 778 for (unsigned i = 0, e = Nest.size(); i < e; ++i) { 779 if (!SCEVCodegen) { 780 PHINode *PN = Nest[i]->getCanonicalInductionVariable(); 781 assert(PN && "Non canonical IV in Scop!"); 782 IVS[i] = PN; 783 } 784 NestLoops[i] = Nest[i]; 785 } 786 787 BaseName = getIslCompatibleName("Stmt_", &bb, ""); 788 789 Domain = buildDomain(tempScop, CurRegion); 790 buildScattering(Scatter); 791 buildAccesses(tempScop, CurRegion); 792 checkForReductions(); 793 } 794 795 /// @brief Collect loads which might form a reduction chain with @p StoreMA 796 /// 797 /// Check if the stored value for @p StoreMA is a binary operator with one or 798 /// two loads as operands. If the binary operand is commutative & associative, 799 /// used only once (by @p StoreMA) and its load operands are also used only 800 /// once, we have found a possible reduction chain. It starts at an operand 801 /// load and includes the binary operator and @p StoreMA. 802 /// 803 /// Note: We allow only one use to ensure the load and binary operator cannot 804 /// escape this block or into any other store except @p StoreMA. 805 void ScopStmt::collectCandiateReductionLoads( 806 MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) { 807 auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction()); 808 if (!Store) 809 return; 810 811 // Skip if there is not one binary operator between the load and the store 812 auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand()); 813 if (!BinOp) 814 return; 815 816 // Skip if the binary operators has multiple uses 817 if (BinOp->getNumUses() != 1) 818 return; 819 820 // Skip if the opcode of the binary operator is not commutative/associative 821 if (!BinOp->isCommutative() || !BinOp->isAssociative()) 822 return; 823 824 // Skip if the binary operator is outside the current SCoP 825 if (BinOp->getParent() != Store->getParent()) 826 return; 827 828 // Skip if it is a multiplicative reduction and we disabled them 829 if (DisableMultiplicativeReductions && 830 (BinOp->getOpcode() == Instruction::Mul || 831 BinOp->getOpcode() == Instruction::FMul)) 832 return; 833 834 // Check the binary operator operands for a candidate load 835 auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0)); 836 auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1)); 837 if (!PossibleLoad0 && !PossibleLoad1) 838 return; 839 840 // A load is only a candidate if it cannot escape (thus has only this use) 841 if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1) 842 if (PossibleLoad0->getParent() == Store->getParent()) 843 Loads.push_back(lookupAccessFor(PossibleLoad0)); 844 if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1) 845 if (PossibleLoad1->getParent() == Store->getParent()) 846 Loads.push_back(lookupAccessFor(PossibleLoad1)); 847 } 848 849 /// @brief Check for reductions in this ScopStmt 850 /// 851 /// Iterate over all store memory accesses and check for valid binary reduction 852 /// like chains. For all candidates we check if they have the same base address 853 /// and there are no other accesses which overlap with them. The base address 854 /// check rules out impossible reductions candidates early. The overlap check, 855 /// together with the "only one user" check in collectCandiateReductionLoads, 856 /// guarantees that none of the intermediate results will escape during 857 /// execution of the loop nest. We basically check here that no other memory 858 /// access can access the same memory as the potential reduction. 859 void ScopStmt::checkForReductions() { 860 SmallVector<MemoryAccess *, 2> Loads; 861 SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates; 862 863 // First collect candidate load-store reduction chains by iterating over all 864 // stores and collecting possible reduction loads. 865 for (MemoryAccess *StoreMA : MemAccs) { 866 if (StoreMA->isRead()) 867 continue; 868 869 Loads.clear(); 870 collectCandiateReductionLoads(StoreMA, Loads); 871 for (MemoryAccess *LoadMA : Loads) 872 Candidates.push_back(std::make_pair(LoadMA, StoreMA)); 873 } 874 875 // Then check each possible candidate pair. 876 for (const auto &CandidatePair : Candidates) { 877 bool Valid = true; 878 isl_map *LoadAccs = CandidatePair.first->getAccessRelation(); 879 isl_map *StoreAccs = CandidatePair.second->getAccessRelation(); 880 881 // Skip those with obviously unequal base addresses. 882 if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) { 883 isl_map_free(LoadAccs); 884 isl_map_free(StoreAccs); 885 continue; 886 } 887 888 // And check if the remaining for overlap with other memory accesses. 889 isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs); 890 AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain()); 891 isl_set *AllAccs = isl_map_range(AllAccsRel); 892 893 for (MemoryAccess *MA : MemAccs) { 894 if (MA == CandidatePair.first || MA == CandidatePair.second) 895 continue; 896 897 isl_map *AccRel = 898 isl_map_intersect_domain(MA->getAccessRelation(), getDomain()); 899 isl_set *Accs = isl_map_range(AccRel); 900 901 if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) { 902 isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs)); 903 Valid = Valid && isl_set_is_empty(OverlapAccs); 904 isl_set_free(OverlapAccs); 905 } 906 } 907 908 isl_set_free(AllAccs); 909 if (!Valid) 910 continue; 911 912 const LoadInst *Load = 913 dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction()); 914 MemoryAccess::ReductionType RT = 915 getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load); 916 917 // If no overlapping access was found we mark the load and store as 918 // reduction like. 919 CandidatePair.first->markAsReductionLike(RT); 920 CandidatePair.second->markAsReductionLike(RT); 921 } 922 } 923 924 std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); } 925 926 std::string ScopStmt::getScatteringStr() const { 927 return stringFromIslObj(Scattering); 928 } 929 930 unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); } 931 932 unsigned ScopStmt::getNumIterators() const { 933 // The final read has one dimension with one element. 934 if (!BB) 935 return 1; 936 937 return NestLoops.size(); 938 } 939 940 unsigned ScopStmt::getNumScattering() const { 941 return isl_map_dim(Scattering, isl_dim_out); 942 } 943 944 const char *ScopStmt::getBaseName() const { return BaseName.c_str(); } 945 946 const PHINode * 947 ScopStmt::getInductionVariableForDimension(unsigned Dimension) const { 948 return IVS[Dimension]; 949 } 950 951 const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const { 952 return NestLoops[Dimension]; 953 } 954 955 isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); } 956 957 isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); } 958 959 isl_space *ScopStmt::getDomainSpace() const { 960 return isl_set_get_space(Domain); 961 } 962 963 isl_id *ScopStmt::getDomainId() const { return isl_set_get_tuple_id(Domain); } 964 965 ScopStmt::~ScopStmt() { 966 while (!MemAccs.empty()) { 967 delete MemAccs.back(); 968 MemAccs.pop_back(); 969 } 970 971 isl_set_free(Domain); 972 isl_map_free(Scattering); 973 } 974 975 void ScopStmt::print(raw_ostream &OS) const { 976 OS << "\t" << getBaseName() << "\n"; 977 OS.indent(12) << "Domain :=\n"; 978 979 if (Domain) { 980 OS.indent(16) << getDomainStr() << ";\n"; 981 } else 982 OS.indent(16) << "n/a\n"; 983 984 OS.indent(12) << "Scattering :=\n"; 985 986 if (Domain) { 987 OS.indent(16) << getScatteringStr() << ";\n"; 988 } else 989 OS.indent(16) << "n/a\n"; 990 991 for (MemoryAccess *Access : MemAccs) 992 Access->print(OS); 993 } 994 995 void ScopStmt::dump() const { print(dbgs()); } 996 997 //===----------------------------------------------------------------------===// 998 /// Scop class implement 999 1000 void Scop::setContext(__isl_take isl_set *NewContext) { 1001 NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context)); 1002 isl_set_free(Context); 1003 Context = NewContext; 1004 } 1005 1006 void Scop::addParams(std::vector<const SCEV *> NewParameters) { 1007 for (const SCEV *Parameter : NewParameters) { 1008 if (ParameterIds.find(Parameter) != ParameterIds.end()) 1009 continue; 1010 1011 int dimension = Parameters.size(); 1012 1013 Parameters.push_back(Parameter); 1014 ParameterIds[Parameter] = dimension; 1015 } 1016 } 1017 1018 __isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) const { 1019 ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter); 1020 1021 if (IdIter == ParameterIds.end()) 1022 return nullptr; 1023 1024 std::string ParameterName; 1025 1026 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) { 1027 Value *Val = ValueParameter->getValue(); 1028 ParameterName = Val->getName(); 1029 } 1030 1031 if (ParameterName == "" || ParameterName.substr(0, 2) == "p_") 1032 ParameterName = "p_" + utostr_32(IdIter->second); 1033 1034 return isl_id_alloc(getIslCtx(), ParameterName.c_str(), 1035 const_cast<void *>((const void *)Parameter)); 1036 } 1037 1038 void Scop::buildContext() { 1039 isl_space *Space = isl_space_params_alloc(IslCtx, 0); 1040 Context = isl_set_universe(isl_space_copy(Space)); 1041 AssumedContext = isl_set_universe(Space); 1042 } 1043 1044 void Scop::addParameterBounds() { 1045 for (unsigned i = 0; i < isl_set_dim(Context, isl_dim_param); ++i) { 1046 isl_val *V; 1047 isl_id *Id; 1048 const SCEV *Scev; 1049 const IntegerType *T; 1050 1051 Id = isl_set_get_dim_id(Context, isl_dim_param, i); 1052 Scev = (const SCEV *)isl_id_get_user(Id); 1053 T = dyn_cast<IntegerType>(Scev->getType()); 1054 isl_id_free(Id); 1055 1056 assert(T && "Not an integer type"); 1057 int Width = T->getBitWidth(); 1058 1059 V = isl_val_int_from_si(IslCtx, Width - 1); 1060 V = isl_val_2exp(V); 1061 V = isl_val_neg(V); 1062 Context = isl_set_lower_bound_val(Context, isl_dim_param, i, V); 1063 1064 V = isl_val_int_from_si(IslCtx, Width - 1); 1065 V = isl_val_2exp(V); 1066 V = isl_val_sub_ui(V, 1); 1067 Context = isl_set_upper_bound_val(Context, isl_dim_param, i, V); 1068 } 1069 } 1070 1071 void Scop::realignParams() { 1072 // Add all parameters into a common model. 1073 isl_space *Space = isl_space_params_alloc(IslCtx, ParameterIds.size()); 1074 1075 for (const auto &ParamID : ParameterIds) { 1076 const SCEV *Parameter = ParamID.first; 1077 isl_id *id = getIdForParam(Parameter); 1078 Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id); 1079 } 1080 1081 // Align the parameters of all data structures to the model. 1082 Context = isl_set_align_params(Context, Space); 1083 1084 for (ScopStmt *Stmt : *this) 1085 Stmt->realignParams(); 1086 } 1087 1088 void Scop::simplifyAssumedContext() { 1089 // The parameter constraints of the iteration domains give us a set of 1090 // constraints that need to hold for all cases where at least a single 1091 // statement iteration is executed in the whole scop. We now simplify the 1092 // assumed context under the assumption that such constraints hold and at 1093 // least a single statement iteration is executed. For cases where no 1094 // statement instances are executed, the assumptions we have taken about 1095 // the executed code do not matter and can be changed. 1096 // 1097 // WARNING: This only holds if the assumptions we have taken do not reduce 1098 // the set of statement instances that are executed. Otherwise we 1099 // may run into a case where the iteration domains suggest that 1100 // for a certain set of parameter constraints no code is executed, 1101 // but in the original program some computation would have been 1102 // performed. In such a case, modifying the run-time conditions and 1103 // possibly influencing the run-time check may cause certain scops 1104 // to not be executed. 1105 // 1106 // Example: 1107 // 1108 // When delinearizing the following code: 1109 // 1110 // for (long i = 0; i < 100; i++) 1111 // for (long j = 0; j < m; j++) 1112 // A[i+p][j] = 1.0; 1113 // 1114 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as 1115 // otherwise we would access out of bound data. Now, knowing that code is 1116 // only executed for the case m >= 0, it is sufficient to assume p >= 0. 1117 AssumedContext = 1118 isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains())); 1119 } 1120 1121 Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution, 1122 isl_ctx *Context) 1123 : SE(&ScalarEvolution), R(tempScop.getMaxRegion()), 1124 MaxLoopDepth(tempScop.getMaxLoopDepth()) { 1125 IslCtx = Context; 1126 buildContext(); 1127 1128 SmallVector<Loop *, 8> NestLoops; 1129 SmallVector<unsigned, 8> Scatter; 1130 1131 Scatter.assign(MaxLoopDepth + 1, 0); 1132 1133 // Build the iteration domain, access functions and scattering functions 1134 // traversing the region tree. 1135 buildScop(tempScop, getRegion(), NestLoops, Scatter, LI); 1136 1137 realignParams(); 1138 addParameterBounds(); 1139 simplifyAssumedContext(); 1140 1141 assert(NestLoops.empty() && "NestLoops not empty at top level!"); 1142 } 1143 1144 Scop::~Scop() { 1145 isl_set_free(Context); 1146 isl_set_free(AssumedContext); 1147 1148 // Free the statements; 1149 for (ScopStmt *Stmt : *this) 1150 delete Stmt; 1151 } 1152 1153 std::string Scop::getContextStr() const { return stringFromIslObj(Context); } 1154 std::string Scop::getAssumedContextStr() const { 1155 return stringFromIslObj(AssumedContext); 1156 } 1157 1158 std::string Scop::getNameStr() const { 1159 std::string ExitName, EntryName; 1160 raw_string_ostream ExitStr(ExitName); 1161 raw_string_ostream EntryStr(EntryName); 1162 1163 R.getEntry()->printAsOperand(EntryStr, false); 1164 EntryStr.str(); 1165 1166 if (R.getExit()) { 1167 R.getExit()->printAsOperand(ExitStr, false); 1168 ExitStr.str(); 1169 } else 1170 ExitName = "FunctionExit"; 1171 1172 return EntryName + "---" + ExitName; 1173 } 1174 1175 __isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); } 1176 __isl_give isl_space *Scop::getParamSpace() const { 1177 return isl_set_get_space(this->Context); 1178 } 1179 1180 __isl_give isl_set *Scop::getAssumedContext() const { 1181 return isl_set_copy(AssumedContext); 1182 } 1183 1184 void Scop::addAssumption(__isl_take isl_set *Set) { 1185 AssumedContext = isl_set_intersect(AssumedContext, Set); 1186 } 1187 1188 void Scop::printContext(raw_ostream &OS) const { 1189 OS << "Context:\n"; 1190 1191 if (!Context) { 1192 OS.indent(4) << "n/a\n\n"; 1193 return; 1194 } 1195 1196 OS.indent(4) << getContextStr() << "\n"; 1197 1198 OS.indent(4) << "Assumed Context:\n"; 1199 if (!AssumedContext) { 1200 OS.indent(4) << "n/a\n\n"; 1201 return; 1202 } 1203 1204 OS.indent(4) << getAssumedContextStr() << "\n"; 1205 1206 for (const SCEV *Parameter : Parameters) { 1207 int Dim = ParameterIds.find(Parameter)->second; 1208 OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n"; 1209 } 1210 } 1211 1212 void Scop::printStatements(raw_ostream &OS) const { 1213 OS << "Statements {\n"; 1214 1215 for (ScopStmt *Stmt : *this) 1216 OS.indent(4) << *Stmt; 1217 1218 OS.indent(4) << "}\n"; 1219 } 1220 1221 void Scop::print(raw_ostream &OS) const { 1222 OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName() 1223 << "\n"; 1224 OS.indent(4) << "Region: " << getNameStr() << "\n"; 1225 printContext(OS.indent(4)); 1226 printStatements(OS.indent(4)); 1227 } 1228 1229 void Scop::dump() const { print(dbgs()); } 1230 1231 isl_ctx *Scop::getIslCtx() const { return IslCtx; } 1232 1233 __isl_give isl_union_set *Scop::getDomains() { 1234 isl_union_set *Domain = isl_union_set_empty(getParamSpace()); 1235 1236 for (ScopStmt *Stmt : *this) 1237 Domain = isl_union_set_add_set(Domain, Stmt->getDomain()); 1238 1239 return Domain; 1240 } 1241 1242 __isl_give isl_union_map *Scop::getMustWrites() { 1243 isl_union_map *Write = isl_union_map_empty(this->getParamSpace()); 1244 1245 for (ScopStmt *Stmt : *this) { 1246 for (MemoryAccess *MA : *Stmt) { 1247 if (!MA->isMustWrite()) 1248 continue; 1249 1250 isl_set *Domain = Stmt->getDomain(); 1251 isl_map *AccessDomain = MA->getAccessRelation(); 1252 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1253 Write = isl_union_map_add_map(Write, AccessDomain); 1254 } 1255 } 1256 return isl_union_map_coalesce(Write); 1257 } 1258 1259 __isl_give isl_union_map *Scop::getMayWrites() { 1260 isl_union_map *Write = isl_union_map_empty(this->getParamSpace()); 1261 1262 for (ScopStmt *Stmt : *this) { 1263 for (MemoryAccess *MA : *Stmt) { 1264 if (!MA->isMayWrite()) 1265 continue; 1266 1267 isl_set *Domain = Stmt->getDomain(); 1268 isl_map *AccessDomain = MA->getAccessRelation(); 1269 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1270 Write = isl_union_map_add_map(Write, AccessDomain); 1271 } 1272 } 1273 return isl_union_map_coalesce(Write); 1274 } 1275 1276 __isl_give isl_union_map *Scop::getWrites() { 1277 isl_union_map *Write = isl_union_map_empty(this->getParamSpace()); 1278 1279 for (ScopStmt *Stmt : *this) { 1280 for (MemoryAccess *MA : *Stmt) { 1281 if (!MA->isWrite()) 1282 continue; 1283 1284 isl_set *Domain = Stmt->getDomain(); 1285 isl_map *AccessDomain = MA->getAccessRelation(); 1286 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1287 Write = isl_union_map_add_map(Write, AccessDomain); 1288 } 1289 } 1290 return isl_union_map_coalesce(Write); 1291 } 1292 1293 __isl_give isl_union_map *Scop::getReads() { 1294 isl_union_map *Read = isl_union_map_empty(getParamSpace()); 1295 1296 for (ScopStmt *Stmt : *this) { 1297 for (MemoryAccess *MA : *Stmt) { 1298 if (!MA->isRead()) 1299 continue; 1300 1301 isl_set *Domain = Stmt->getDomain(); 1302 isl_map *AccessDomain = MA->getAccessRelation(); 1303 1304 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1305 Read = isl_union_map_add_map(Read, AccessDomain); 1306 } 1307 } 1308 return isl_union_map_coalesce(Read); 1309 } 1310 1311 __isl_give isl_union_map *Scop::getSchedule() { 1312 isl_union_map *Schedule = isl_union_map_empty(getParamSpace()); 1313 1314 for (ScopStmt *Stmt : *this) 1315 Schedule = isl_union_map_add_map(Schedule, Stmt->getScattering()); 1316 1317 return isl_union_map_coalesce(Schedule); 1318 } 1319 1320 bool Scop::restrictDomains(__isl_take isl_union_set *Domain) { 1321 bool Changed = false; 1322 for (ScopStmt *Stmt : *this) { 1323 isl_union_set *StmtDomain = isl_union_set_from_set(Stmt->getDomain()); 1324 isl_union_set *NewStmtDomain = isl_union_set_intersect( 1325 isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain)); 1326 1327 if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) { 1328 isl_union_set_free(StmtDomain); 1329 isl_union_set_free(NewStmtDomain); 1330 continue; 1331 } 1332 1333 Changed = true; 1334 1335 isl_union_set_free(StmtDomain); 1336 NewStmtDomain = isl_union_set_coalesce(NewStmtDomain); 1337 1338 if (isl_union_set_is_empty(NewStmtDomain)) { 1339 Stmt->restrictDomain(isl_set_empty(Stmt->getDomainSpace())); 1340 isl_union_set_free(NewStmtDomain); 1341 } else 1342 Stmt->restrictDomain(isl_set_from_union_set(NewStmtDomain)); 1343 } 1344 isl_union_set_free(Domain); 1345 return Changed; 1346 } 1347 1348 ScalarEvolution *Scop::getSE() const { return SE; } 1349 1350 bool Scop::isTrivialBB(BasicBlock *BB, TempScop &tempScop) { 1351 if (tempScop.getAccessFunctions(BB)) 1352 return false; 1353 1354 return true; 1355 } 1356 1357 void Scop::buildScop(TempScop &tempScop, const Region &CurRegion, 1358 SmallVectorImpl<Loop *> &NestLoops, 1359 SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI) { 1360 Loop *L = castToLoop(CurRegion, LI); 1361 1362 if (L) 1363 NestLoops.push_back(L); 1364 1365 unsigned loopDepth = NestLoops.size(); 1366 assert(Scatter.size() > loopDepth && "Scatter not big enough!"); 1367 1368 for (Region::const_element_iterator I = CurRegion.element_begin(), 1369 E = CurRegion.element_end(); 1370 I != E; ++I) 1371 if (I->isSubRegion()) 1372 buildScop(tempScop, *(I->getNodeAs<Region>()), NestLoops, Scatter, LI); 1373 else { 1374 BasicBlock *BB = I->getNodeAs<BasicBlock>(); 1375 1376 if (isTrivialBB(BB, tempScop)) 1377 continue; 1378 1379 Stmts.push_back( 1380 new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter)); 1381 1382 // Increasing the Scattering function is OK for the moment, because 1383 // we are using a depth first iterator and the program is well structured. 1384 ++Scatter[loopDepth]; 1385 } 1386 1387 if (!L) 1388 return; 1389 1390 // Exiting a loop region. 1391 Scatter[loopDepth] = 0; 1392 NestLoops.pop_back(); 1393 ++Scatter[loopDepth - 1]; 1394 } 1395 1396 //===----------------------------------------------------------------------===// 1397 ScopInfo::ScopInfo() : RegionPass(ID), scop(0) { 1398 ctx = isl_ctx_alloc(); 1399 isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT); 1400 } 1401 1402 ScopInfo::~ScopInfo() { 1403 clear(); 1404 isl_ctx_free(ctx); 1405 } 1406 1407 void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const { 1408 AU.addRequired<LoopInfo>(); 1409 AU.addRequired<RegionInfoPass>(); 1410 AU.addRequired<ScalarEvolution>(); 1411 AU.addRequired<TempScopInfo>(); 1412 AU.setPreservesAll(); 1413 } 1414 1415 bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) { 1416 LoopInfo &LI = getAnalysis<LoopInfo>(); 1417 ScalarEvolution &SE = getAnalysis<ScalarEvolution>(); 1418 1419 TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R); 1420 1421 // This region is no Scop. 1422 if (!tempScop) { 1423 scop = 0; 1424 return false; 1425 } 1426 1427 // Statistics. 1428 ++ScopFound; 1429 if (tempScop->getMaxLoopDepth() > 0) 1430 ++RichScopFound; 1431 1432 scop = new Scop(*tempScop, LI, SE, ctx); 1433 1434 return false; 1435 } 1436 1437 char ScopInfo::ID = 0; 1438 1439 Pass *polly::createScopInfoPass() { return new ScopInfo(); } 1440 1441 INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops", 1442 "Polly - Create polyhedral description of Scops", false, 1443 false); 1444 INITIALIZE_PASS_DEPENDENCY(LoopInfo); 1445 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 1446 INITIALIZE_PASS_DEPENDENCY(ScalarEvolution); 1447 INITIALIZE_PASS_DEPENDENCY(TempScopInfo); 1448 INITIALIZE_PASS_END(ScopInfo, "polly-scops", 1449 "Polly - Create polyhedral description of Scops", false, 1450 false) 1451