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 representation is shared among several tools in the polyhedral 16 // community, which are e.g. Cloog, Pluto, Loopo, Graphite. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #include "polly/LinkAllPasses.h" 21 #include "polly/ScopInfo.h" 22 #include "polly/Options.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/AliasAnalysis.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 separately 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 static cl::opt<unsigned> RunTimeChecksMaxParameters( 67 "polly-rtc-max-parameters", 68 cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden, 69 cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory)); 70 71 /// Translate a 'const SCEV *' expression in an isl_pw_aff. 72 struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff *> { 73 public: 74 /// @brief Translate a 'const SCEV *' to an isl_pw_aff. 75 /// 76 /// @param Stmt The location at which the scalar evolution expression 77 /// is evaluated. 78 /// @param Expr The expression that is translated. 79 static __isl_give isl_pw_aff *getPwAff(ScopStmt *Stmt, const SCEV *Expr); 80 81 private: 82 isl_ctx *Ctx; 83 int NbLoopSpaces; 84 const Scop *S; 85 86 SCEVAffinator(const ScopStmt *Stmt); 87 int getLoopDepth(const Loop *L); 88 89 __isl_give isl_pw_aff *visit(const SCEV *Expr); 90 __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Expr); 91 __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr *Expr); 92 __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr); 93 __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr *Expr); 94 __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr *Expr); 95 __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr *Expr); 96 __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr *Expr); 97 __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr *Expr); 98 __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr *Expr); 99 __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr *Expr); 100 __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown *Expr); 101 __isl_give isl_pw_aff *visitSDivInstruction(Instruction *SDiv); 102 103 friend struct SCEVVisitor<SCEVAffinator, isl_pw_aff *>; 104 }; 105 106 SCEVAffinator::SCEVAffinator(const ScopStmt *Stmt) 107 : Ctx(Stmt->getIslCtx()), NbLoopSpaces(Stmt->getNumIterators()), 108 S(Stmt->getParent()) {} 109 110 __isl_give isl_pw_aff *SCEVAffinator::getPwAff(ScopStmt *Stmt, 111 const SCEV *Scev) { 112 Scop *S = Stmt->getParent(); 113 const Region *Reg = &S->getRegion(); 114 115 S->addParams(getParamsInAffineExpr(Reg, Scev, *S->getSE())); 116 117 SCEVAffinator Affinator(Stmt); 118 return Affinator.visit(Scev); 119 } 120 121 __isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) { 122 // In case the scev is a valid parameter, we do not further analyze this 123 // expression, but create a new parameter in the isl_pw_aff. This allows us 124 // to treat subexpressions that we cannot translate into an piecewise affine 125 // expression, as constant parameters of the piecewise affine expression. 126 if (isl_id *Id = S->getIdForParam(Expr)) { 127 isl_space *Space = isl_space_set_alloc(Ctx, 1, NbLoopSpaces); 128 Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id); 129 130 isl_set *Domain = isl_set_universe(isl_space_copy(Space)); 131 isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space)); 132 Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1); 133 134 return isl_pw_aff_alloc(Domain, Affine); 135 } 136 137 return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr); 138 } 139 140 __isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) { 141 ConstantInt *Value = Expr->getValue(); 142 isl_val *v; 143 144 // LLVM does not define if an integer value is interpreted as a signed or 145 // unsigned value. Hence, without further information, it is unknown how 146 // this value needs to be converted to GMP. At the moment, we only support 147 // signed operations. So we just interpret it as signed. Later, there are 148 // two options: 149 // 150 // 1. We always interpret any value as signed and convert the values on 151 // demand. 152 // 2. We pass down the signedness of the calculation and use it to interpret 153 // this constant correctly. 154 v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true); 155 156 isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces); 157 isl_local_space *ls = isl_local_space_from_space(Space); 158 return isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v)); 159 } 160 161 __isl_give isl_pw_aff * 162 SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) { 163 llvm_unreachable("SCEVTruncateExpr not yet supported"); 164 } 165 166 __isl_give isl_pw_aff * 167 SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { 168 llvm_unreachable("SCEVZeroExtendExpr not yet supported"); 169 } 170 171 __isl_give isl_pw_aff * 172 SCEVAffinator::visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { 173 // Assuming the value is signed, a sign extension is basically a noop. 174 // TODO: Reconsider this as soon as we support unsigned values. 175 return visit(Expr->getOperand()); 176 } 177 178 __isl_give isl_pw_aff *SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) { 179 isl_pw_aff *Sum = visit(Expr->getOperand(0)); 180 181 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { 182 isl_pw_aff *NextSummand = visit(Expr->getOperand(i)); 183 Sum = isl_pw_aff_add(Sum, NextSummand); 184 } 185 186 // TODO: Check for NSW and NUW. 187 188 return Sum; 189 } 190 191 __isl_give isl_pw_aff *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) { 192 isl_pw_aff *Product = visit(Expr->getOperand(0)); 193 194 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { 195 isl_pw_aff *NextOperand = visit(Expr->getOperand(i)); 196 197 if (!isl_pw_aff_is_cst(Product) && !isl_pw_aff_is_cst(NextOperand)) { 198 isl_pw_aff_free(Product); 199 isl_pw_aff_free(NextOperand); 200 return nullptr; 201 } 202 203 Product = isl_pw_aff_mul(Product, NextOperand); 204 } 205 206 // TODO: Check for NSW and NUW. 207 return Product; 208 } 209 210 __isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) { 211 llvm_unreachable("SCEVUDivExpr not yet supported"); 212 } 213 214 __isl_give isl_pw_aff * 215 SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) { 216 assert(Expr->isAffine() && "Only affine AddRecurrences allowed"); 217 218 // Directly generate isl_pw_aff for Expr if 'start' is zero. 219 if (Expr->getStart()->isZero()) { 220 assert(S->getRegion().contains(Expr->getLoop()) && 221 "Scop does not contain the loop referenced in this AddRec"); 222 223 isl_pw_aff *Start = visit(Expr->getStart()); 224 isl_pw_aff *Step = visit(Expr->getOperand(1)); 225 isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces); 226 isl_local_space *LocalSpace = isl_local_space_from_space(Space); 227 228 int loopDimension = getLoopDepth(Expr->getLoop()); 229 230 isl_aff *LAff = isl_aff_set_coefficient_si( 231 isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1); 232 isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff); 233 234 // TODO: Do we need to check for NSW and NUW? 235 return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff)); 236 } 237 238 // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}' 239 // if 'start' is not zero. 240 ScalarEvolution &SE = *S->getSE(); 241 const SCEV *ZeroStartExpr = SE.getAddRecExpr( 242 SE.getConstant(Expr->getStart()->getType(), 0), 243 Expr->getStepRecurrence(SE), Expr->getLoop(), SCEV::FlagAnyWrap); 244 245 isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr); 246 isl_pw_aff *Start = visit(Expr->getStart()); 247 248 return isl_pw_aff_add(ZeroStartResult, Start); 249 } 250 251 __isl_give isl_pw_aff *SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) { 252 isl_pw_aff *Max = visit(Expr->getOperand(0)); 253 254 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { 255 isl_pw_aff *NextOperand = visit(Expr->getOperand(i)); 256 Max = isl_pw_aff_max(Max, NextOperand); 257 } 258 259 return Max; 260 } 261 262 __isl_give isl_pw_aff *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) { 263 llvm_unreachable("SCEVUMaxExpr not yet supported"); 264 } 265 266 __isl_give isl_pw_aff *SCEVAffinator::visitSDivInstruction(Instruction *SDiv) { 267 assert(SDiv->getOpcode() == Instruction::SDiv && "Assumed SDiv instruction!"); 268 auto *SE = S->getSE(); 269 270 auto *Divisor = SDiv->getOperand(1); 271 auto *DivisorSCEV = SE->getSCEV(Divisor); 272 auto *DivisorPWA = visit(DivisorSCEV); 273 assert(isa<ConstantInt>(Divisor) && 274 "SDiv is no parameter but has a non-constant RHS."); 275 276 auto *Dividend = SDiv->getOperand(0); 277 auto *DividendSCEV = SE->getSCEV(Dividend); 278 auto *DividendPWA = visit(DividendSCEV); 279 return isl_pw_aff_tdiv_q(DividendPWA, DivisorPWA); 280 } 281 282 __isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) { 283 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) { 284 switch (I->getOpcode()) { 285 case Instruction::SDiv: 286 return visitSDivInstruction(I); 287 default: 288 break; // Fall through. 289 } 290 } 291 292 llvm_unreachable( 293 "Unknowns SCEV was neither parameter nor a valid instruction."); 294 } 295 296 int SCEVAffinator::getLoopDepth(const Loop *L) { 297 Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L)); 298 assert(outerLoop && "Scop does not contain this loop"); 299 return L->getLoopDepth() - outerLoop->getLoopDepth(); 300 } 301 302 /// @brief Add the bounds of @p Range to the set @p S for dimension @p dim. 303 static __isl_give isl_set *addRangeBoundsToSet(__isl_take isl_set *S, 304 const ConstantRange &Range, 305 int dim, 306 enum isl_dim_type type) { 307 isl_val *V; 308 isl_ctx *ctx = isl_set_get_ctx(S); 309 310 V = isl_valFromAPInt(ctx, Range.getLower(), true); 311 isl_set *SLB = isl_set_lower_bound_val(isl_set_copy(S), type, dim, V); 312 313 V = isl_valFromAPInt(ctx, Range.getUpper(), true); 314 V = isl_val_sub_ui(V, 1); 315 isl_set *SUB = isl_set_upper_bound_val(S, type, dim, V); 316 317 if (Range.isSignWrappedSet()) 318 return isl_set_union(SLB, SUB); 319 else 320 return isl_set_intersect(SLB, SUB); 321 } 322 323 ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *AccessType, isl_ctx *Ctx, 324 const SmallVector<const SCEV *, 4> &DimensionSizes) 325 : BasePtr(BasePtr), AccessType(AccessType), DimensionSizes(DimensionSizes) { 326 const std::string BasePtrName = getIslCompatibleName("MemRef_", BasePtr, ""); 327 Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this); 328 } 329 330 ScopArrayInfo::~ScopArrayInfo() { isl_id_free(Id); } 331 332 isl_id *ScopArrayInfo::getBasePtrId() const { return isl_id_copy(Id); } 333 334 void ScopArrayInfo::dump() const { print(errs()); } 335 336 void ScopArrayInfo::print(raw_ostream &OS) const { 337 OS << "ScopArrayInfo:\n"; 338 OS << " Base: " << *getBasePtr() << "\n"; 339 OS << " Type: " << *getType() << "\n"; 340 OS << " Dimension Sizes:\n"; 341 for (unsigned u = 0; u < getNumberOfDimensions(); u++) 342 OS << " " << u << ") " << *DimensionSizes[u] << "\n"; 343 OS << "\n"; 344 } 345 346 const ScopArrayInfo * 347 ScopArrayInfo::getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA) { 348 isl_id *Id = isl_pw_multi_aff_get_tuple_id(PMA, isl_dim_out); 349 assert(Id && "Output dimension didn't have an ID"); 350 return getFromId(Id); 351 } 352 353 const ScopArrayInfo *ScopArrayInfo::getFromId(isl_id *Id) { 354 void *User = isl_id_get_user(Id); 355 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 356 isl_id_free(Id); 357 return SAI; 358 } 359 360 const std::string 361 MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) { 362 switch (RT) { 363 case MemoryAccess::RT_NONE: 364 llvm_unreachable("Requested a reduction operator string for a memory " 365 "access which isn't a reduction"); 366 case MemoryAccess::RT_ADD: 367 return "+"; 368 case MemoryAccess::RT_MUL: 369 return "*"; 370 case MemoryAccess::RT_BOR: 371 return "|"; 372 case MemoryAccess::RT_BXOR: 373 return "^"; 374 case MemoryAccess::RT_BAND: 375 return "&"; 376 } 377 llvm_unreachable("Unknown reduction type"); 378 return ""; 379 } 380 381 /// @brief Return the reduction type for a given binary operator 382 static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp, 383 const Instruction *Load) { 384 if (!BinOp) 385 return MemoryAccess::RT_NONE; 386 switch (BinOp->getOpcode()) { 387 case Instruction::FAdd: 388 if (!BinOp->hasUnsafeAlgebra()) 389 return MemoryAccess::RT_NONE; 390 // Fall through 391 case Instruction::Add: 392 return MemoryAccess::RT_ADD; 393 case Instruction::Or: 394 return MemoryAccess::RT_BOR; 395 case Instruction::Xor: 396 return MemoryAccess::RT_BXOR; 397 case Instruction::And: 398 return MemoryAccess::RT_BAND; 399 case Instruction::FMul: 400 if (!BinOp->hasUnsafeAlgebra()) 401 return MemoryAccess::RT_NONE; 402 // Fall through 403 case Instruction::Mul: 404 if (DisableMultiplicativeReductions) 405 return MemoryAccess::RT_NONE; 406 return MemoryAccess::RT_MUL; 407 default: 408 return MemoryAccess::RT_NONE; 409 } 410 } 411 //===----------------------------------------------------------------------===// 412 413 MemoryAccess::~MemoryAccess() { 414 isl_map_free(AccessRelation); 415 isl_map_free(newAccessRelation); 416 } 417 418 static MemoryAccess::AccessType getMemoryAccessType(const IRAccess &Access) { 419 switch (Access.getType()) { 420 case IRAccess::READ: 421 return MemoryAccess::READ; 422 case IRAccess::MUST_WRITE: 423 return MemoryAccess::MUST_WRITE; 424 case IRAccess::MAY_WRITE: 425 return MemoryAccess::MAY_WRITE; 426 } 427 llvm_unreachable("Unknown IRAccess type!"); 428 } 429 430 const ScopArrayInfo *MemoryAccess::getScopArrayInfo() const { 431 isl_id *ArrayId = getArrayId(); 432 void *User = isl_id_get_user(ArrayId); 433 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 434 isl_id_free(ArrayId); 435 return SAI; 436 } 437 438 isl_id *MemoryAccess::getArrayId() const { 439 return isl_map_get_tuple_id(AccessRelation, isl_dim_out); 440 } 441 442 isl_pw_multi_aff * 443 MemoryAccess::applyScheduleToAccessRelation(isl_union_map *USchedule) const { 444 isl_map *Schedule, *ScheduledAccRel; 445 isl_union_set *UDomain; 446 447 UDomain = isl_union_set_from_set(getStatement()->getDomain()); 448 USchedule = isl_union_map_intersect_domain(USchedule, UDomain); 449 Schedule = isl_map_from_union_map(USchedule); 450 ScheduledAccRel = isl_map_apply_domain(getAccessRelation(), Schedule); 451 return isl_pw_multi_aff_from_map(ScheduledAccRel); 452 } 453 454 isl_map *MemoryAccess::getOriginalAccessRelation() const { 455 return isl_map_copy(AccessRelation); 456 } 457 458 std::string MemoryAccess::getOriginalAccessRelationStr() const { 459 return stringFromIslObj(AccessRelation); 460 } 461 462 __isl_give isl_space *MemoryAccess::getOriginalAccessRelationSpace() const { 463 return isl_map_get_space(AccessRelation); 464 } 465 466 isl_map *MemoryAccess::getNewAccessRelation() const { 467 return isl_map_copy(newAccessRelation); 468 } 469 470 isl_basic_map *MemoryAccess::createBasicAccessMap(ScopStmt *Statement) { 471 isl_space *Space = isl_space_set_alloc(Statement->getIslCtx(), 0, 1); 472 Space = isl_space_align_params(Space, Statement->getDomainSpace()); 473 474 return isl_basic_map_from_domain_and_range( 475 isl_basic_set_universe(Statement->getDomainSpace()), 476 isl_basic_set_universe(Space)); 477 } 478 479 // Formalize no out-of-bound access assumption 480 // 481 // When delinearizing array accesses we optimistically assume that the 482 // delinearized accesses do not access out of bound locations (the subscript 483 // expression of each array evaluates for each statement instance that is 484 // executed to a value that is larger than zero and strictly smaller than the 485 // size of the corresponding dimension). The only exception is the outermost 486 // dimension for which we do not need to assume any upper bound. At this point 487 // we formalize this assumption to ensure that at code generation time the 488 // relevant run-time checks can be generated. 489 // 490 // To find the set of constraints necessary to avoid out of bound accesses, we 491 // first build the set of data locations that are not within array bounds. We 492 // then apply the reverse access relation to obtain the set of iterations that 493 // may contain invalid accesses and reduce this set of iterations to the ones 494 // that are actually executed by intersecting them with the domain of the 495 // statement. If we now project out all loop dimensions, we obtain a set of 496 // parameters that may cause statement instances to be executed that may 497 // possibly yield out of bound memory accesses. The complement of these 498 // constraints is the set of constraints that needs to be assumed to ensure such 499 // statement instances are never executed. 500 void MemoryAccess::assumeNoOutOfBound(const IRAccess &Access) { 501 isl_space *Space = isl_space_range(getOriginalAccessRelationSpace()); 502 isl_set *Outside = isl_set_empty(isl_space_copy(Space)); 503 for (int i = 1, Size = Access.Subscripts.size(); i < Size; ++i) { 504 isl_local_space *LS = isl_local_space_from_space(isl_space_copy(Space)); 505 isl_pw_aff *Var = 506 isl_pw_aff_var_on_domain(isl_local_space_copy(LS), isl_dim_set, i); 507 isl_pw_aff *Zero = isl_pw_aff_zero_on_domain(LS); 508 509 isl_set *DimOutside; 510 511 DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero); 512 isl_pw_aff *SizeE = SCEVAffinator::getPwAff(Statement, Access.Sizes[i - 1]); 513 514 SizeE = isl_pw_aff_drop_dims(SizeE, isl_dim_in, 0, 515 Statement->getNumIterators()); 516 SizeE = isl_pw_aff_add_dims(SizeE, isl_dim_in, 517 isl_space_dim(Space, isl_dim_set)); 518 SizeE = isl_pw_aff_set_tuple_id(SizeE, isl_dim_in, 519 isl_space_get_tuple_id(Space, isl_dim_set)); 520 521 DimOutside = isl_set_union(DimOutside, isl_pw_aff_le_set(SizeE, Var)); 522 523 Outside = isl_set_union(Outside, DimOutside); 524 } 525 526 Outside = isl_set_apply(Outside, isl_map_reverse(getAccessRelation())); 527 Outside = isl_set_intersect(Outside, Statement->getDomain()); 528 Outside = isl_set_params(Outside); 529 Outside = isl_set_complement(Outside); 530 Statement->getParent()->addAssumption(Outside); 531 isl_space_free(Space); 532 } 533 534 void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) { 535 ScalarEvolution *SE = Statement->getParent()->getSE(); 536 537 Value *Ptr = getPointerOperand(*getAccessInstruction()); 538 if (!Ptr || !SE->isSCEVable(Ptr->getType())) 539 return; 540 541 auto *PtrSCEV = SE->getSCEV(Ptr); 542 if (isa<SCEVCouldNotCompute>(PtrSCEV)) 543 return; 544 545 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV); 546 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV)) 547 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV); 548 549 const ConstantRange &Range = SE->getSignedRange(PtrSCEV); 550 if (Range.isFullSet()) 551 return; 552 553 unsigned BW = Range.getBitWidth(); 554 auto Min = Range.getSignedMin().sdiv(APInt(BW, ElementSize)); 555 auto Max = (Range.getSignedMax() - APInt(BW, 1)).sdiv(APInt(BW, ElementSize)); 556 557 isl_set *AccessRange = isl_map_range(isl_map_copy(AccessRelation)); 558 AccessRange = 559 addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0, isl_dim_set); 560 AccessRelation = isl_map_intersect_range(AccessRelation, AccessRange); 561 } 562 563 MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst, 564 ScopStmt *Statement, const ScopArrayInfo *SAI) 565 : AccType(getMemoryAccessType(Access)), Statement(Statement), Inst(AccInst), 566 newAccessRelation(nullptr) { 567 568 isl_ctx *Ctx = Statement->getIslCtx(); 569 BaseAddr = Access.getBase(); 570 BaseName = getIslCompatibleName("MemRef_", getBaseAddr(), ""); 571 572 isl_id *BaseAddrId = SAI->getBasePtrId(); 573 574 if (!Access.isAffine()) { 575 // We overapproximate non-affine accesses with a possible access to the 576 // whole array. For read accesses it does not make a difference, if an 577 // access must or may happen. However, for write accesses it is important to 578 // differentiate between writes that must happen and writes that may happen. 579 AccessRelation = isl_map_from_basic_map(createBasicAccessMap(Statement)); 580 AccessRelation = 581 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId); 582 583 computeBoundsOnAccessRelation(Access.getElemSizeInBytes()); 584 return; 585 } 586 587 isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0); 588 AccessRelation = isl_map_universe(Space); 589 590 for (int i = 0, Size = Access.Subscripts.size(); i < Size; ++i) { 591 isl_pw_aff *Affine = 592 SCEVAffinator::getPwAff(Statement, Access.Subscripts[i]); 593 594 if (Size == 1) { 595 // For the non delinearized arrays, divide the access function of the last 596 // subscript by the size of the elements in the array. 597 // 598 // A stride one array access in C expressed as A[i] is expressed in 599 // LLVM-IR as something like A[i * elementsize]. This hides the fact that 600 // two subsequent values of 'i' index two values that are stored next to 601 // each other in memory. By this division we make this characteristic 602 // obvious again. 603 isl_val *v = isl_val_int_from_si(Ctx, Access.getElemSizeInBytes()); 604 Affine = isl_pw_aff_scale_down_val(Affine, v); 605 } 606 607 isl_map *SubscriptMap = isl_map_from_pw_aff(Affine); 608 609 AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap); 610 } 611 612 Space = Statement->getDomainSpace(); 613 AccessRelation = isl_map_set_tuple_id( 614 AccessRelation, isl_dim_in, isl_space_get_tuple_id(Space, isl_dim_set)); 615 AccessRelation = 616 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId); 617 618 assumeNoOutOfBound(Access); 619 isl_space_free(Space); 620 } 621 622 void MemoryAccess::realignParams() { 623 isl_space *ParamSpace = Statement->getParent()->getParamSpace(); 624 AccessRelation = isl_map_align_params(AccessRelation, ParamSpace); 625 } 626 627 const std::string MemoryAccess::getReductionOperatorStr() const { 628 return MemoryAccess::getReductionOperatorStr(getReductionType()); 629 } 630 631 raw_ostream &polly::operator<<(raw_ostream &OS, 632 MemoryAccess::ReductionType RT) { 633 if (RT == MemoryAccess::RT_NONE) 634 OS << "NONE"; 635 else 636 OS << MemoryAccess::getReductionOperatorStr(RT); 637 return OS; 638 } 639 640 void MemoryAccess::print(raw_ostream &OS) const { 641 switch (AccType) { 642 case READ: 643 OS.indent(12) << "ReadAccess :=\t"; 644 break; 645 case MUST_WRITE: 646 OS.indent(12) << "MustWriteAccess :=\t"; 647 break; 648 case MAY_WRITE: 649 OS.indent(12) << "MayWriteAccess :=\t"; 650 break; 651 } 652 OS << "[Reduction Type: " << getReductionType() << "] "; 653 OS << "[Scalar: " << isScalar() << "]\n"; 654 OS.indent(16) << getOriginalAccessRelationStr() << ";\n"; 655 } 656 657 void MemoryAccess::dump() const { print(errs()); } 658 659 // Create a map in the size of the provided set domain, that maps from the 660 // one element of the provided set domain to another element of the provided 661 // set domain. 662 // The mapping is limited to all points that are equal in all but the last 663 // dimension and for which the last dimension of the input is strict smaller 664 // than the last dimension of the output. 665 // 666 // getEqualAndLarger(set[i0, i1, ..., iX]): 667 // 668 // set[i0, i1, ..., iX] -> set[o0, o1, ..., oX] 669 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX 670 // 671 static isl_map *getEqualAndLarger(isl_space *setDomain) { 672 isl_space *Space = isl_space_map_from_set(setDomain); 673 isl_map *Map = isl_map_universe(isl_space_copy(Space)); 674 isl_local_space *MapLocalSpace = isl_local_space_from_space(Space); 675 unsigned lastDimension = isl_map_dim(Map, isl_dim_in) - 1; 676 677 // Set all but the last dimension to be equal for the input and output 678 // 679 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX] 680 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1) 681 for (unsigned i = 0; i < lastDimension; ++i) 682 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); 683 684 // Set the last dimension of the input to be strict smaller than the 685 // last dimension of the output. 686 // 687 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX 688 // 689 isl_val *v; 690 isl_ctx *Ctx = isl_map_get_ctx(Map); 691 isl_constraint *c = isl_inequality_alloc(isl_local_space_copy(MapLocalSpace)); 692 v = isl_val_int_from_si(Ctx, -1); 693 c = isl_constraint_set_coefficient_val(c, isl_dim_in, lastDimension, v); 694 v = isl_val_int_from_si(Ctx, 1); 695 c = isl_constraint_set_coefficient_val(c, isl_dim_out, lastDimension, v); 696 v = isl_val_int_from_si(Ctx, -1); 697 c = isl_constraint_set_constant_val(c, v); 698 699 Map = isl_map_add_constraint(Map, c); 700 701 isl_local_space_free(MapLocalSpace); 702 return Map; 703 } 704 705 isl_set *MemoryAccess::getStride(__isl_take const isl_map *Schedule) const { 706 isl_map *S = const_cast<isl_map *>(Schedule); 707 isl_map *AccessRelation = getAccessRelation(); 708 isl_space *Space = isl_space_range(isl_map_get_space(S)); 709 isl_map *NextScatt = getEqualAndLarger(Space); 710 711 S = isl_map_reverse(S); 712 NextScatt = isl_map_lexmin(NextScatt); 713 714 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S)); 715 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation)); 716 NextScatt = isl_map_apply_domain(NextScatt, S); 717 NextScatt = isl_map_apply_domain(NextScatt, AccessRelation); 718 719 isl_set *Deltas = isl_map_deltas(NextScatt); 720 return Deltas; 721 } 722 723 bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule, 724 int StrideWidth) const { 725 isl_set *Stride, *StrideX; 726 bool IsStrideX; 727 728 Stride = getStride(Schedule); 729 StrideX = isl_set_universe(isl_set_get_space(Stride)); 730 StrideX = isl_set_fix_si(StrideX, isl_dim_set, 0, StrideWidth); 731 IsStrideX = isl_set_is_equal(Stride, StrideX); 732 733 isl_set_free(StrideX); 734 isl_set_free(Stride); 735 736 return IsStrideX; 737 } 738 739 bool MemoryAccess::isStrideZero(const isl_map *Schedule) const { 740 return isStrideX(Schedule, 0); 741 } 742 743 bool MemoryAccess::isScalar() const { 744 return isl_map_n_out(AccessRelation) == 0; 745 } 746 747 bool MemoryAccess::isStrideOne(const isl_map *Schedule) const { 748 return isStrideX(Schedule, 1); 749 } 750 751 void MemoryAccess::setNewAccessRelation(isl_map *newAccess) { 752 isl_map_free(newAccessRelation); 753 newAccessRelation = newAccess; 754 } 755 756 //===----------------------------------------------------------------------===// 757 758 isl_map *ScopStmt::getScattering() const { return isl_map_copy(Scattering); } 759 760 void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) { 761 assert(isl_set_is_subset(NewDomain, Domain) && 762 "New domain is not a subset of old domain!"); 763 isl_set_free(Domain); 764 Domain = NewDomain; 765 Scattering = isl_map_intersect_domain(Scattering, isl_set_copy(Domain)); 766 } 767 768 void ScopStmt::setScattering(isl_map *NewScattering) { 769 assert(NewScattering && "New scattering is nullptr"); 770 isl_map_free(Scattering); 771 Scattering = NewScattering; 772 } 773 774 void ScopStmt::buildScattering(SmallVectorImpl<unsigned> &Scatter) { 775 unsigned NbIterators = getNumIterators(); 776 unsigned NbScatteringDims = Parent.getMaxLoopDepth() * 2 + 1; 777 778 isl_space *Space = isl_space_set_alloc(getIslCtx(), 0, NbScatteringDims); 779 780 Scattering = isl_map_from_domain_and_range(isl_set_universe(getDomainSpace()), 781 isl_set_universe(Space)); 782 783 // Loop dimensions. 784 for (unsigned i = 0; i < NbIterators; ++i) 785 Scattering = 786 isl_map_equate(Scattering, isl_dim_out, 2 * i + 1, isl_dim_in, i); 787 788 // Constant dimensions 789 for (unsigned i = 0; i < NbIterators + 1; ++i) 790 Scattering = isl_map_fix_si(Scattering, isl_dim_out, 2 * i, Scatter[i]); 791 792 // Fill scattering dimensions. 793 for (unsigned i = 2 * NbIterators + 1; i < NbScatteringDims; ++i) 794 Scattering = isl_map_fix_si(Scattering, isl_dim_out, i, 0); 795 796 Scattering = isl_map_align_params(Scattering, Parent.getParamSpace()); 797 } 798 799 void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block, 800 bool isApproximated) { 801 AccFuncSetType *AFS = tempScop.getAccessFunctions(Block); 802 if (!AFS) 803 return; 804 805 for (auto &AccessPair : *AFS) { 806 IRAccess &Access = AccessPair.first; 807 Instruction *AccessInst = AccessPair.second; 808 809 Type *AccessType = getAccessInstType(AccessInst)->getPointerTo(); 810 const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo( 811 Access.getBase(), AccessType, Access.Sizes); 812 813 if (isApproximated && Access.isWrite()) 814 Access.setMayWrite(); 815 816 MemAccs.push_back(new MemoryAccess(Access, AccessInst, this, SAI)); 817 818 // We do not track locations for scalar memory accesses at the moment. 819 // 820 // We do not have a use for this information at the moment. If we need this 821 // at some point, the "instruction -> access" mapping needs to be enhanced 822 // as a single instruction could then possibly perform multiple accesses. 823 if (!Access.isScalar()) { 824 assert(!InstructionToAccess.count(AccessInst) && 825 "Unexpected 1-to-N mapping on instruction to access map!"); 826 InstructionToAccess[AccessInst] = MemAccs.back(); 827 } 828 } 829 } 830 831 void ScopStmt::realignParams() { 832 for (MemoryAccess *MA : *this) 833 MA->realignParams(); 834 835 Domain = isl_set_align_params(Domain, Parent.getParamSpace()); 836 Scattering = isl_map_align_params(Scattering, Parent.getParamSpace()); 837 } 838 839 __isl_give isl_set *ScopStmt::buildConditionSet(const Comparison &Comp) { 840 isl_pw_aff *L = SCEVAffinator::getPwAff(this, Comp.getLHS()); 841 isl_pw_aff *R = SCEVAffinator::getPwAff(this, Comp.getRHS()); 842 843 switch (Comp.getPred()) { 844 case ICmpInst::ICMP_EQ: 845 return isl_pw_aff_eq_set(L, R); 846 case ICmpInst::ICMP_NE: 847 return isl_pw_aff_ne_set(L, R); 848 case ICmpInst::ICMP_SLT: 849 return isl_pw_aff_lt_set(L, R); 850 case ICmpInst::ICMP_SLE: 851 return isl_pw_aff_le_set(L, R); 852 case ICmpInst::ICMP_SGT: 853 return isl_pw_aff_gt_set(L, R); 854 case ICmpInst::ICMP_SGE: 855 return isl_pw_aff_ge_set(L, R); 856 case ICmpInst::ICMP_ULT: 857 return isl_pw_aff_lt_set(L, R); 858 case ICmpInst::ICMP_UGT: 859 return isl_pw_aff_gt_set(L, R); 860 case ICmpInst::ICMP_ULE: 861 return isl_pw_aff_le_set(L, R); 862 case ICmpInst::ICMP_UGE: 863 return isl_pw_aff_ge_set(L, R); 864 default: 865 llvm_unreachable("Non integer predicate not supported"); 866 } 867 } 868 869 __isl_give isl_set *ScopStmt::addLoopBoundsToDomain(__isl_take isl_set *Domain, 870 TempScop &tempScop) { 871 isl_space *Space; 872 isl_local_space *LocalSpace; 873 874 Space = isl_set_get_space(Domain); 875 LocalSpace = isl_local_space_from_space(Space); 876 877 ScalarEvolution *SE = getParent()->getSE(); 878 for (int i = 0, e = getNumIterators(); i != e; ++i) { 879 isl_aff *Zero = isl_aff_zero_on_domain(isl_local_space_copy(LocalSpace)); 880 isl_pw_aff *IV = 881 isl_pw_aff_from_aff(isl_aff_set_coefficient_si(Zero, isl_dim_in, i, 1)); 882 883 // 0 <= IV. 884 isl_set *LowerBound = isl_pw_aff_nonneg_set(isl_pw_aff_copy(IV)); 885 Domain = isl_set_intersect(Domain, LowerBound); 886 887 // IV <= LatchExecutions. 888 const Loop *L = getLoopForDimension(i); 889 const SCEV *LatchExecutions = SE->getBackedgeTakenCount(L); 890 isl_pw_aff *UpperBound = SCEVAffinator::getPwAff(this, LatchExecutions); 891 isl_set *UpperBoundSet = isl_pw_aff_le_set(IV, UpperBound); 892 Domain = isl_set_intersect(Domain, UpperBoundSet); 893 } 894 895 isl_local_space_free(LocalSpace); 896 return Domain; 897 } 898 899 __isl_give isl_set *ScopStmt::addConditionsToDomain(__isl_take isl_set *Domain, 900 TempScop &tempScop, 901 const Region &CurRegion) { 902 const Region *TopRegion = tempScop.getMaxRegion().getParent(), 903 *CurrentRegion = &CurRegion; 904 const BasicBlock *BranchingBB = BB ? BB : R->getEntry(); 905 906 do { 907 if (BranchingBB != CurrentRegion->getEntry()) { 908 if (const BBCond *Condition = tempScop.getBBCond(BranchingBB)) 909 for (const auto &C : *Condition) { 910 isl_set *ConditionSet = buildConditionSet(C); 911 Domain = isl_set_intersect(Domain, ConditionSet); 912 } 913 } 914 BranchingBB = CurrentRegion->getEntry(); 915 CurrentRegion = CurrentRegion->getParent(); 916 } while (TopRegion != CurrentRegion); 917 918 return Domain; 919 } 920 921 __isl_give isl_set *ScopStmt::buildDomain(TempScop &tempScop, 922 const Region &CurRegion) { 923 isl_space *Space; 924 isl_set *Domain; 925 isl_id *Id; 926 927 Space = isl_space_set_alloc(getIslCtx(), 0, getNumIterators()); 928 929 Id = isl_id_alloc(getIslCtx(), getBaseName(), this); 930 931 Domain = isl_set_universe(Space); 932 Domain = addLoopBoundsToDomain(Domain, tempScop); 933 Domain = addConditionsToDomain(Domain, tempScop, CurRegion); 934 Domain = isl_set_set_tuple_id(Domain, Id); 935 936 return Domain; 937 } 938 939 void ScopStmt::deriveAssumptionsFromGEP(GetElementPtrInst *GEP) { 940 int Dimension = 0; 941 isl_ctx *Ctx = Parent.getIslCtx(); 942 isl_local_space *LSpace = isl_local_space_from_space(getDomainSpace()); 943 Type *Ty = GEP->getPointerOperandType(); 944 ScalarEvolution &SE = *Parent.getSE(); 945 946 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) { 947 Dimension = 1; 948 Ty = PtrTy->getElementType(); 949 } 950 951 while (auto ArrayTy = dyn_cast<ArrayType>(Ty)) { 952 unsigned int Operand = 1 + Dimension; 953 954 if (GEP->getNumOperands() <= Operand) 955 break; 956 957 const SCEV *Expr = SE.getSCEV(GEP->getOperand(Operand)); 958 959 if (isAffineExpr(&Parent.getRegion(), Expr, SE)) { 960 isl_pw_aff *AccessOffset = SCEVAffinator::getPwAff(this, Expr); 961 AccessOffset = 962 isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId()); 963 964 isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain( 965 isl_local_space_copy(LSpace), 966 isl_val_int_from_si(Ctx, ArrayTy->getNumElements()))); 967 968 isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize); 969 OutOfBound = isl_set_intersect(getDomain(), OutOfBound); 970 OutOfBound = isl_set_params(OutOfBound); 971 isl_set *InBound = isl_set_complement(OutOfBound); 972 isl_set *Executed = isl_set_params(getDomain()); 973 974 // A => B == !A or B 975 isl_set *InBoundIfExecuted = 976 isl_set_union(isl_set_complement(Executed), InBound); 977 978 Parent.addAssumption(InBoundIfExecuted); 979 } 980 981 Dimension += 1; 982 Ty = ArrayTy->getElementType(); 983 } 984 985 isl_local_space_free(LSpace); 986 } 987 988 void ScopStmt::deriveAssumptions(BasicBlock *Block) { 989 for (Instruction &Inst : *Block) 990 if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst)) 991 deriveAssumptionsFromGEP(GEP); 992 } 993 994 ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion, 995 Region &R, SmallVectorImpl<Loop *> &Nest, 996 SmallVectorImpl<unsigned> &Scatter) 997 : Parent(parent), BB(nullptr), R(&R), Build(nullptr), 998 NestLoops(Nest.size()) { 999 // Setup the induction variables. 1000 for (unsigned i = 0, e = Nest.size(); i < e; ++i) 1001 NestLoops[i] = Nest[i]; 1002 1003 BaseName = getIslCompatibleName("Stmt_(", R.getNameStr(), ")"); 1004 1005 Domain = buildDomain(tempScop, CurRegion); 1006 buildScattering(Scatter); 1007 1008 BasicBlock *EntryBB = R.getEntry(); 1009 for (BasicBlock *Block : R.blocks()) { 1010 buildAccesses(tempScop, Block, Block != EntryBB); 1011 deriveAssumptions(Block); 1012 } 1013 checkForReductions(); 1014 } 1015 1016 ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion, 1017 BasicBlock &bb, SmallVectorImpl<Loop *> &Nest, 1018 SmallVectorImpl<unsigned> &Scatter) 1019 : Parent(parent), BB(&bb), R(nullptr), Build(nullptr), 1020 NestLoops(Nest.size()) { 1021 // Setup the induction variables. 1022 for (unsigned i = 0, e = Nest.size(); i < e; ++i) 1023 NestLoops[i] = Nest[i]; 1024 1025 BaseName = getIslCompatibleName("Stmt_", &bb, ""); 1026 1027 Domain = buildDomain(tempScop, CurRegion); 1028 buildScattering(Scatter); 1029 buildAccesses(tempScop, BB); 1030 deriveAssumptions(BB); 1031 checkForReductions(); 1032 } 1033 1034 /// @brief Collect loads which might form a reduction chain with @p StoreMA 1035 /// 1036 /// Check if the stored value for @p StoreMA is a binary operator with one or 1037 /// two loads as operands. If the binary operand is commutative & associative, 1038 /// used only once (by @p StoreMA) and its load operands are also used only 1039 /// once, we have found a possible reduction chain. It starts at an operand 1040 /// load and includes the binary operator and @p StoreMA. 1041 /// 1042 /// Note: We allow only one use to ensure the load and binary operator cannot 1043 /// escape this block or into any other store except @p StoreMA. 1044 void ScopStmt::collectCandiateReductionLoads( 1045 MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) { 1046 auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction()); 1047 if (!Store) 1048 return; 1049 1050 // Skip if there is not one binary operator between the load and the store 1051 auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand()); 1052 if (!BinOp) 1053 return; 1054 1055 // Skip if the binary operators has multiple uses 1056 if (BinOp->getNumUses() != 1) 1057 return; 1058 1059 // Skip if the opcode of the binary operator is not commutative/associative 1060 if (!BinOp->isCommutative() || !BinOp->isAssociative()) 1061 return; 1062 1063 // Skip if the binary operator is outside the current SCoP 1064 if (BinOp->getParent() != Store->getParent()) 1065 return; 1066 1067 // Skip if it is a multiplicative reduction and we disabled them 1068 if (DisableMultiplicativeReductions && 1069 (BinOp->getOpcode() == Instruction::Mul || 1070 BinOp->getOpcode() == Instruction::FMul)) 1071 return; 1072 1073 // Check the binary operator operands for a candidate load 1074 auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0)); 1075 auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1)); 1076 if (!PossibleLoad0 && !PossibleLoad1) 1077 return; 1078 1079 // A load is only a candidate if it cannot escape (thus has only this use) 1080 if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1) 1081 if (PossibleLoad0->getParent() == Store->getParent()) 1082 Loads.push_back(lookupAccessFor(PossibleLoad0)); 1083 if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1) 1084 if (PossibleLoad1->getParent() == Store->getParent()) 1085 Loads.push_back(lookupAccessFor(PossibleLoad1)); 1086 } 1087 1088 /// @brief Check for reductions in this ScopStmt 1089 /// 1090 /// Iterate over all store memory accesses and check for valid binary reduction 1091 /// like chains. For all candidates we check if they have the same base address 1092 /// and there are no other accesses which overlap with them. The base address 1093 /// check rules out impossible reductions candidates early. The overlap check, 1094 /// together with the "only one user" check in collectCandiateReductionLoads, 1095 /// guarantees that none of the intermediate results will escape during 1096 /// execution of the loop nest. We basically check here that no other memory 1097 /// access can access the same memory as the potential reduction. 1098 void ScopStmt::checkForReductions() { 1099 SmallVector<MemoryAccess *, 2> Loads; 1100 SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates; 1101 1102 // First collect candidate load-store reduction chains by iterating over all 1103 // stores and collecting possible reduction loads. 1104 for (MemoryAccess *StoreMA : MemAccs) { 1105 if (StoreMA->isRead()) 1106 continue; 1107 1108 Loads.clear(); 1109 collectCandiateReductionLoads(StoreMA, Loads); 1110 for (MemoryAccess *LoadMA : Loads) 1111 Candidates.push_back(std::make_pair(LoadMA, StoreMA)); 1112 } 1113 1114 // Then check each possible candidate pair. 1115 for (const auto &CandidatePair : Candidates) { 1116 bool Valid = true; 1117 isl_map *LoadAccs = CandidatePair.first->getAccessRelation(); 1118 isl_map *StoreAccs = CandidatePair.second->getAccessRelation(); 1119 1120 // Skip those with obviously unequal base addresses. 1121 if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) { 1122 isl_map_free(LoadAccs); 1123 isl_map_free(StoreAccs); 1124 continue; 1125 } 1126 1127 // And check if the remaining for overlap with other memory accesses. 1128 isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs); 1129 AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain()); 1130 isl_set *AllAccs = isl_map_range(AllAccsRel); 1131 1132 for (MemoryAccess *MA : MemAccs) { 1133 if (MA == CandidatePair.first || MA == CandidatePair.second) 1134 continue; 1135 1136 isl_map *AccRel = 1137 isl_map_intersect_domain(MA->getAccessRelation(), getDomain()); 1138 isl_set *Accs = isl_map_range(AccRel); 1139 1140 if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) { 1141 isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs)); 1142 Valid = Valid && isl_set_is_empty(OverlapAccs); 1143 isl_set_free(OverlapAccs); 1144 } 1145 } 1146 1147 isl_set_free(AllAccs); 1148 if (!Valid) 1149 continue; 1150 1151 const LoadInst *Load = 1152 dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction()); 1153 MemoryAccess::ReductionType RT = 1154 getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load); 1155 1156 // If no overlapping access was found we mark the load and store as 1157 // reduction like. 1158 CandidatePair.first->markAsReductionLike(RT); 1159 CandidatePair.second->markAsReductionLike(RT); 1160 } 1161 } 1162 1163 std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); } 1164 1165 std::string ScopStmt::getScatteringStr() const { 1166 return stringFromIslObj(Scattering); 1167 } 1168 1169 unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); } 1170 1171 unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); } 1172 1173 unsigned ScopStmt::getNumScattering() const { 1174 return isl_map_dim(Scattering, isl_dim_out); 1175 } 1176 1177 const char *ScopStmt::getBaseName() const { return BaseName.c_str(); } 1178 1179 const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const { 1180 return NestLoops[Dimension]; 1181 } 1182 1183 isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); } 1184 1185 isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); } 1186 1187 isl_space *ScopStmt::getDomainSpace() const { 1188 return isl_set_get_space(Domain); 1189 } 1190 1191 isl_id *ScopStmt::getDomainId() const { return isl_set_get_tuple_id(Domain); } 1192 1193 ScopStmt::~ScopStmt() { 1194 while (!MemAccs.empty()) { 1195 delete MemAccs.back(); 1196 MemAccs.pop_back(); 1197 } 1198 1199 isl_set_free(Domain); 1200 isl_map_free(Scattering); 1201 } 1202 1203 void ScopStmt::print(raw_ostream &OS) const { 1204 OS << "\t" << getBaseName() << "\n"; 1205 OS.indent(12) << "Domain :=\n"; 1206 1207 if (Domain) { 1208 OS.indent(16) << getDomainStr() << ";\n"; 1209 } else 1210 OS.indent(16) << "n/a\n"; 1211 1212 OS.indent(12) << "Scattering :=\n"; 1213 1214 if (Domain) { 1215 OS.indent(16) << getScatteringStr() << ";\n"; 1216 } else 1217 OS.indent(16) << "n/a\n"; 1218 1219 for (MemoryAccess *Access : MemAccs) 1220 Access->print(OS); 1221 } 1222 1223 void ScopStmt::dump() const { print(dbgs()); } 1224 1225 //===----------------------------------------------------------------------===// 1226 /// Scop class implement 1227 1228 void Scop::setContext(__isl_take isl_set *NewContext) { 1229 NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context)); 1230 isl_set_free(Context); 1231 Context = NewContext; 1232 } 1233 1234 void Scop::addParams(std::vector<const SCEV *> NewParameters) { 1235 for (const SCEV *Parameter : NewParameters) { 1236 if (ParameterIds.find(Parameter) != ParameterIds.end()) 1237 continue; 1238 1239 int dimension = Parameters.size(); 1240 1241 Parameters.push_back(Parameter); 1242 ParameterIds[Parameter] = dimension; 1243 } 1244 } 1245 1246 __isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) const { 1247 ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter); 1248 1249 if (IdIter == ParameterIds.end()) 1250 return nullptr; 1251 1252 std::string ParameterName; 1253 1254 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) { 1255 Value *Val = ValueParameter->getValue(); 1256 ParameterName = Val->getName(); 1257 } 1258 1259 if (ParameterName == "" || ParameterName.substr(0, 2) == "p_") 1260 ParameterName = "p_" + utostr_32(IdIter->second); 1261 1262 return isl_id_alloc(getIslCtx(), ParameterName.c_str(), 1263 const_cast<void *>((const void *)Parameter)); 1264 } 1265 1266 void Scop::buildContext() { 1267 isl_space *Space = isl_space_params_alloc(IslCtx, 0); 1268 Context = isl_set_universe(isl_space_copy(Space)); 1269 AssumedContext = isl_set_universe(Space); 1270 } 1271 1272 void Scop::addParameterBounds() { 1273 for (const auto &ParamID : ParameterIds) { 1274 int dim = ParamID.second; 1275 1276 ConstantRange SRange = SE->getSignedRange(ParamID.first); 1277 1278 // TODO: Find a case where the full set is actually helpful. 1279 if (SRange.isFullSet()) 1280 continue; 1281 1282 Context = addRangeBoundsToSet(Context, SRange, dim, isl_dim_param); 1283 } 1284 } 1285 1286 void Scop::realignParams() { 1287 // Add all parameters into a common model. 1288 isl_space *Space = isl_space_params_alloc(IslCtx, ParameterIds.size()); 1289 1290 for (const auto &ParamID : ParameterIds) { 1291 const SCEV *Parameter = ParamID.first; 1292 isl_id *id = getIdForParam(Parameter); 1293 Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id); 1294 } 1295 1296 // Align the parameters of all data structures to the model. 1297 Context = isl_set_align_params(Context, Space); 1298 1299 for (ScopStmt *Stmt : *this) 1300 Stmt->realignParams(); 1301 } 1302 1303 void Scop::simplifyAssumedContext() { 1304 // The parameter constraints of the iteration domains give us a set of 1305 // constraints that need to hold for all cases where at least a single 1306 // statement iteration is executed in the whole scop. We now simplify the 1307 // assumed context under the assumption that such constraints hold and at 1308 // least a single statement iteration is executed. For cases where no 1309 // statement instances are executed, the assumptions we have taken about 1310 // the executed code do not matter and can be changed. 1311 // 1312 // WARNING: This only holds if the assumptions we have taken do not reduce 1313 // the set of statement instances that are executed. Otherwise we 1314 // may run into a case where the iteration domains suggest that 1315 // for a certain set of parameter constraints no code is executed, 1316 // but in the original program some computation would have been 1317 // performed. In such a case, modifying the run-time conditions and 1318 // possibly influencing the run-time check may cause certain scops 1319 // to not be executed. 1320 // 1321 // Example: 1322 // 1323 // When delinearizing the following code: 1324 // 1325 // for (long i = 0; i < 100; i++) 1326 // for (long j = 0; j < m; j++) 1327 // A[i+p][j] = 1.0; 1328 // 1329 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as 1330 // otherwise we would access out of bound data. Now, knowing that code is 1331 // only executed for the case m >= 0, it is sufficient to assume p >= 0. 1332 AssumedContext = 1333 isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains())); 1334 AssumedContext = isl_set_gist_params(AssumedContext, getContext()); 1335 } 1336 1337 /// @brief Add the minimal/maximal access in @p Set to @p User. 1338 static int buildMinMaxAccess(__isl_take isl_set *Set, void *User) { 1339 Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User; 1340 isl_pw_multi_aff *MinPMA, *MaxPMA; 1341 isl_pw_aff *LastDimAff; 1342 isl_aff *OneAff; 1343 unsigned Pos; 1344 1345 // Restrict the number of parameters involved in the access as the lexmin/ 1346 // lexmax computation will take too long if this number is high. 1347 // 1348 // Experiments with a simple test case using an i7 4800MQ: 1349 // 1350 // #Parameters involved | Time (in sec) 1351 // 6 | 0.01 1352 // 7 | 0.04 1353 // 8 | 0.12 1354 // 9 | 0.40 1355 // 10 | 1.54 1356 // 11 | 6.78 1357 // 12 | 30.38 1358 // 1359 if (isl_set_n_param(Set) > RunTimeChecksMaxParameters) { 1360 unsigned InvolvedParams = 0; 1361 for (unsigned u = 0, e = isl_set_n_param(Set); u < e; u++) 1362 if (isl_set_involves_dims(Set, isl_dim_param, u, 1)) 1363 InvolvedParams++; 1364 1365 if (InvolvedParams > RunTimeChecksMaxParameters) { 1366 isl_set_free(Set); 1367 return -1; 1368 } 1369 } 1370 1371 Set = isl_set_remove_divs(Set); 1372 1373 MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set)); 1374 MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set)); 1375 1376 MinPMA = isl_pw_multi_aff_coalesce(MinPMA); 1377 MaxPMA = isl_pw_multi_aff_coalesce(MaxPMA); 1378 1379 // Adjust the last dimension of the maximal access by one as we want to 1380 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer 1381 // we test during code generation might now point after the end of the 1382 // allocated array but we will never dereference it anyway. 1383 assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) && 1384 "Assumed at least one output dimension"); 1385 Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1; 1386 LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos); 1387 OneAff = isl_aff_zero_on_domain( 1388 isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff))); 1389 OneAff = isl_aff_add_constant_si(OneAff, 1); 1390 LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff)); 1391 MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff); 1392 1393 MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA)); 1394 1395 isl_set_free(Set); 1396 return 0; 1397 } 1398 1399 static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) { 1400 isl_set *Domain = MA->getStatement()->getDomain(); 1401 Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain)); 1402 return isl_set_reset_tuple_id(Domain); 1403 } 1404 1405 bool Scop::buildAliasGroups(AliasAnalysis &AA) { 1406 // To create sound alias checks we perform the following steps: 1407 // o) Use the alias analysis and an alias set tracker to build alias sets 1408 // for all memory accesses inside the SCoP. 1409 // o) For each alias set we then map the aliasing pointers back to the 1410 // memory accesses we know, thus obtain groups of memory accesses which 1411 // might alias. 1412 // o) We divide each group based on the domains of the minimal/maximal 1413 // accesses. That means two minimal/maximal accesses are only in a group 1414 // if their access domains intersect, otherwise they are in different 1415 // ones. 1416 // o) We split groups such that they contain at most one read only base 1417 // address. 1418 // o) For each group with more than one base pointer we then compute minimal 1419 // and maximal accesses to each array in this group. 1420 using AliasGroupTy = SmallVector<MemoryAccess *, 4>; 1421 1422 AliasSetTracker AST(AA); 1423 1424 DenseMap<Value *, MemoryAccess *> PtrToAcc; 1425 DenseSet<Value *> HasWriteAccess; 1426 for (ScopStmt *Stmt : *this) { 1427 1428 // Skip statements with an empty domain as they will never be executed. 1429 isl_set *StmtDomain = Stmt->getDomain(); 1430 bool StmtDomainEmpty = isl_set_is_empty(StmtDomain); 1431 isl_set_free(StmtDomain); 1432 if (StmtDomainEmpty) 1433 continue; 1434 1435 for (MemoryAccess *MA : *Stmt) { 1436 if (MA->isScalar()) 1437 continue; 1438 if (!MA->isRead()) 1439 HasWriteAccess.insert(MA->getBaseAddr()); 1440 Instruction *Acc = MA->getAccessInstruction(); 1441 PtrToAcc[getPointerOperand(*Acc)] = MA; 1442 AST.add(Acc); 1443 } 1444 } 1445 1446 SmallVector<AliasGroupTy, 4> AliasGroups; 1447 for (AliasSet &AS : AST) { 1448 if (AS.isMustAlias() || AS.isForwardingAliasSet()) 1449 continue; 1450 AliasGroupTy AG; 1451 for (auto PR : AS) 1452 AG.push_back(PtrToAcc[PR.getValue()]); 1453 assert(AG.size() > 1 && 1454 "Alias groups should contain at least two accesses"); 1455 AliasGroups.push_back(std::move(AG)); 1456 } 1457 1458 // Split the alias groups based on their domain. 1459 for (unsigned u = 0; u < AliasGroups.size(); u++) { 1460 AliasGroupTy NewAG; 1461 AliasGroupTy &AG = AliasGroups[u]; 1462 AliasGroupTy::iterator AGI = AG.begin(); 1463 isl_set *AGDomain = getAccessDomain(*AGI); 1464 while (AGI != AG.end()) { 1465 MemoryAccess *MA = *AGI; 1466 isl_set *MADomain = getAccessDomain(MA); 1467 if (isl_set_is_disjoint(AGDomain, MADomain)) { 1468 NewAG.push_back(MA); 1469 AGI = AG.erase(AGI); 1470 isl_set_free(MADomain); 1471 } else { 1472 AGDomain = isl_set_union(AGDomain, MADomain); 1473 AGI++; 1474 } 1475 } 1476 if (NewAG.size() > 1) 1477 AliasGroups.push_back(std::move(NewAG)); 1478 isl_set_free(AGDomain); 1479 } 1480 1481 DenseMap<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs; 1482 SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues; 1483 for (AliasGroupTy &AG : AliasGroups) { 1484 NonReadOnlyBaseValues.clear(); 1485 ReadOnlyPairs.clear(); 1486 1487 if (AG.size() < 2) { 1488 AG.clear(); 1489 continue; 1490 } 1491 1492 for (auto II = AG.begin(); II != AG.end();) { 1493 Value *BaseAddr = (*II)->getBaseAddr(); 1494 if (HasWriteAccess.count(BaseAddr)) { 1495 NonReadOnlyBaseValues.insert(BaseAddr); 1496 II++; 1497 } else { 1498 ReadOnlyPairs[BaseAddr].insert(*II); 1499 II = AG.erase(II); 1500 } 1501 } 1502 1503 // If we don't have read only pointers check if there are at least two 1504 // non read only pointers, otherwise clear the alias group. 1505 if (ReadOnlyPairs.empty()) { 1506 if (NonReadOnlyBaseValues.size() <= 1) 1507 AG.clear(); 1508 continue; 1509 } 1510 1511 // If we don't have non read only pointers clear the alias group. 1512 if (NonReadOnlyBaseValues.empty()) { 1513 AG.clear(); 1514 continue; 1515 } 1516 1517 // If we have both read only and non read only base pointers we combine 1518 // the non read only ones with exactly one read only one at a time into a 1519 // new alias group and clear the old alias group in the end. 1520 for (const auto &ReadOnlyPair : ReadOnlyPairs) { 1521 AliasGroupTy AGNonReadOnly = AG; 1522 for (MemoryAccess *MA : ReadOnlyPair.second) 1523 AGNonReadOnly.push_back(MA); 1524 AliasGroups.push_back(std::move(AGNonReadOnly)); 1525 } 1526 AG.clear(); 1527 } 1528 1529 bool Valid = true; 1530 for (AliasGroupTy &AG : AliasGroups) { 1531 if (AG.empty()) 1532 continue; 1533 1534 MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy(); 1535 MinMaxAccesses->reserve(AG.size()); 1536 1537 isl_union_map *Accesses = isl_union_map_empty(getParamSpace()); 1538 for (MemoryAccess *MA : AG) 1539 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation()); 1540 Accesses = isl_union_map_intersect_domain(Accesses, getDomains()); 1541 1542 isl_union_set *Locations = isl_union_map_range(Accesses); 1543 Locations = isl_union_set_intersect_params(Locations, getAssumedContext()); 1544 Locations = isl_union_set_coalesce(Locations); 1545 Locations = isl_union_set_detect_equalities(Locations); 1546 Valid = (0 == isl_union_set_foreach_set(Locations, buildMinMaxAccess, 1547 MinMaxAccesses)); 1548 isl_union_set_free(Locations); 1549 MinMaxAliasGroups.push_back(MinMaxAccesses); 1550 1551 if (!Valid) 1552 break; 1553 } 1554 1555 return Valid; 1556 } 1557 1558 static unsigned getMaxLoopDepthInRegion(const Region &R, LoopInfo &LI) { 1559 unsigned MinLD = INT_MAX, MaxLD = 0; 1560 for (BasicBlock *BB : R.blocks()) { 1561 if (Loop *L = LI.getLoopFor(BB)) { 1562 if (!R.contains(L)) 1563 continue; 1564 unsigned LD = L->getLoopDepth(); 1565 MinLD = std::min(MinLD, LD); 1566 MaxLD = std::max(MaxLD, LD); 1567 } 1568 } 1569 1570 // Handle the case that there is no loop in the SCoP first. 1571 if (MaxLD == 0) 1572 return 1; 1573 1574 assert(MinLD >= 1 && "Minimal loop depth should be at least one"); 1575 assert(MaxLD >= MinLD && 1576 "Maximal loop depth was smaller than mininaml loop depth?"); 1577 return MaxLD - MinLD + 1; 1578 } 1579 1580 void Scop::dropConstantScheduleDims() { 1581 isl_union_map *FullSchedule = getSchedule(); 1582 1583 if (isl_union_map_n_map(FullSchedule) == 0) { 1584 isl_union_map_free(FullSchedule); 1585 return; 1586 } 1587 1588 isl_set *ScheduleSpace = 1589 isl_set_from_union_set(isl_union_map_range(FullSchedule)); 1590 isl_map *DropDimMap = isl_set_identity(isl_set_copy(ScheduleSpace)); 1591 1592 int NumDimsDropped = 0; 1593 for (unsigned i = 0; i < isl_set_dim(ScheduleSpace, isl_dim_set); i++) 1594 if (i % 2 == 0) { 1595 isl_val *FixedVal = 1596 isl_set_plain_get_val_if_fixed(ScheduleSpace, isl_dim_set, i); 1597 if (isl_val_is_int(FixedVal)) { 1598 DropDimMap = 1599 isl_map_project_out(DropDimMap, isl_dim_out, i - NumDimsDropped, 1); 1600 NumDimsDropped++; 1601 } 1602 isl_val_free(FixedVal); 1603 } 1604 1605 for (auto *S : *this) { 1606 isl_map *Schedule = S->getScattering(); 1607 Schedule = isl_map_apply_range(Schedule, isl_map_copy(DropDimMap)); 1608 S->setScattering(Schedule); 1609 } 1610 isl_set_free(ScheduleSpace); 1611 isl_map_free(DropDimMap); 1612 } 1613 1614 Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution, 1615 ScopDetection &SD, isl_ctx *Context) 1616 : SE(&ScalarEvolution), R(tempScop.getMaxRegion()), IsOptimized(false), 1617 MaxLoopDepth(getMaxLoopDepthInRegion(tempScop.getMaxRegion(), LI)) { 1618 IslCtx = Context; 1619 1620 buildContext(); 1621 1622 SmallVector<Loop *, 8> NestLoops; 1623 SmallVector<unsigned, 8> Scatter; 1624 1625 Scatter.assign(MaxLoopDepth + 1, 0); 1626 1627 // Build the iteration domain, access functions and scattering functions 1628 // traversing the region tree. 1629 buildScop(tempScop, getRegion(), NestLoops, Scatter, LI, SD); 1630 1631 realignParams(); 1632 addParameterBounds(); 1633 simplifyAssumedContext(); 1634 dropConstantScheduleDims(); 1635 1636 assert(NestLoops.empty() && "NestLoops not empty at top level!"); 1637 } 1638 1639 Scop::~Scop() { 1640 isl_set_free(Context); 1641 isl_set_free(AssumedContext); 1642 1643 // Free the statements; 1644 for (ScopStmt *Stmt : *this) 1645 delete Stmt; 1646 1647 // Free the ScopArrayInfo objects. 1648 for (auto &ScopArrayInfoPair : ScopArrayInfoMap) 1649 delete ScopArrayInfoPair.second; 1650 1651 // Free the alias groups 1652 for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) { 1653 for (MinMaxAccessTy &MMA : *MinMaxAccesses) { 1654 isl_pw_multi_aff_free(MMA.first); 1655 isl_pw_multi_aff_free(MMA.second); 1656 } 1657 delete MinMaxAccesses; 1658 } 1659 } 1660 1661 const ScopArrayInfo * 1662 Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType, 1663 const SmallVector<const SCEV *, 4> &Sizes) { 1664 const ScopArrayInfo *&SAI = ScopArrayInfoMap[BasePtr]; 1665 if (!SAI) 1666 SAI = new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Sizes); 1667 return SAI; 1668 } 1669 1670 const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr) { 1671 const SCEV *PtrSCEV = SE->getSCEV(BasePtr); 1672 const SCEVUnknown *PtrBaseSCEV = 1673 cast<SCEVUnknown>(SE->getPointerBase(PtrSCEV)); 1674 const ScopArrayInfo *SAI = ScopArrayInfoMap[PtrBaseSCEV->getValue()]; 1675 assert(SAI && "No ScopArrayInfo available for this base pointer"); 1676 return SAI; 1677 } 1678 1679 std::string Scop::getContextStr() const { return stringFromIslObj(Context); } 1680 std::string Scop::getAssumedContextStr() const { 1681 return stringFromIslObj(AssumedContext); 1682 } 1683 1684 std::string Scop::getNameStr() const { 1685 std::string ExitName, EntryName; 1686 raw_string_ostream ExitStr(ExitName); 1687 raw_string_ostream EntryStr(EntryName); 1688 1689 R.getEntry()->printAsOperand(EntryStr, false); 1690 EntryStr.str(); 1691 1692 if (R.getExit()) { 1693 R.getExit()->printAsOperand(ExitStr, false); 1694 ExitStr.str(); 1695 } else 1696 ExitName = "FunctionExit"; 1697 1698 return EntryName + "---" + ExitName; 1699 } 1700 1701 __isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); } 1702 __isl_give isl_space *Scop::getParamSpace() const { 1703 return isl_set_get_space(this->Context); 1704 } 1705 1706 __isl_give isl_set *Scop::getAssumedContext() const { 1707 return isl_set_copy(AssumedContext); 1708 } 1709 1710 void Scop::addAssumption(__isl_take isl_set *Set) { 1711 AssumedContext = isl_set_intersect(AssumedContext, Set); 1712 AssumedContext = isl_set_coalesce(AssumedContext); 1713 } 1714 1715 void Scop::printContext(raw_ostream &OS) const { 1716 OS << "Context:\n"; 1717 1718 if (!Context) { 1719 OS.indent(4) << "n/a\n\n"; 1720 return; 1721 } 1722 1723 OS.indent(4) << getContextStr() << "\n"; 1724 1725 OS.indent(4) << "Assumed Context:\n"; 1726 if (!AssumedContext) { 1727 OS.indent(4) << "n/a\n\n"; 1728 return; 1729 } 1730 1731 OS.indent(4) << getAssumedContextStr() << "\n"; 1732 1733 for (const SCEV *Parameter : Parameters) { 1734 int Dim = ParameterIds.find(Parameter)->second; 1735 OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n"; 1736 } 1737 } 1738 1739 void Scop::printAliasAssumptions(raw_ostream &OS) const { 1740 OS.indent(4) << "Alias Groups (" << MinMaxAliasGroups.size() << "):\n"; 1741 if (MinMaxAliasGroups.empty()) { 1742 OS.indent(8) << "n/a\n"; 1743 return; 1744 } 1745 for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) { 1746 OS.indent(8) << "[["; 1747 for (MinMaxAccessTy &MinMacAccess : *MinMaxAccesses) 1748 OS << " <" << MinMacAccess.first << ", " << MinMacAccess.second << ">"; 1749 OS << " ]]\n"; 1750 } 1751 } 1752 1753 void Scop::printStatements(raw_ostream &OS) const { 1754 OS << "Statements {\n"; 1755 1756 for (ScopStmt *Stmt : *this) 1757 OS.indent(4) << *Stmt; 1758 1759 OS.indent(4) << "}\n"; 1760 } 1761 1762 void Scop::print(raw_ostream &OS) const { 1763 OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName() 1764 << "\n"; 1765 OS.indent(4) << "Region: " << getNameStr() << "\n"; 1766 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; 1767 printContext(OS.indent(4)); 1768 printAliasAssumptions(OS); 1769 printStatements(OS.indent(4)); 1770 } 1771 1772 void Scop::dump() const { print(dbgs()); } 1773 1774 isl_ctx *Scop::getIslCtx() const { return IslCtx; } 1775 1776 __isl_give isl_union_set *Scop::getDomains() { 1777 isl_union_set *Domain = isl_union_set_empty(getParamSpace()); 1778 1779 for (ScopStmt *Stmt : *this) 1780 Domain = isl_union_set_add_set(Domain, Stmt->getDomain()); 1781 1782 return Domain; 1783 } 1784 1785 __isl_give isl_union_map *Scop::getMustWrites() { 1786 isl_union_map *Write = isl_union_map_empty(this->getParamSpace()); 1787 1788 for (ScopStmt *Stmt : *this) { 1789 for (MemoryAccess *MA : *Stmt) { 1790 if (!MA->isMustWrite()) 1791 continue; 1792 1793 isl_set *Domain = Stmt->getDomain(); 1794 isl_map *AccessDomain = MA->getAccessRelation(); 1795 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1796 Write = isl_union_map_add_map(Write, AccessDomain); 1797 } 1798 } 1799 return isl_union_map_coalesce(Write); 1800 } 1801 1802 __isl_give isl_union_map *Scop::getMayWrites() { 1803 isl_union_map *Write = isl_union_map_empty(this->getParamSpace()); 1804 1805 for (ScopStmt *Stmt : *this) { 1806 for (MemoryAccess *MA : *Stmt) { 1807 if (!MA->isMayWrite()) 1808 continue; 1809 1810 isl_set *Domain = Stmt->getDomain(); 1811 isl_map *AccessDomain = MA->getAccessRelation(); 1812 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1813 Write = isl_union_map_add_map(Write, AccessDomain); 1814 } 1815 } 1816 return isl_union_map_coalesce(Write); 1817 } 1818 1819 __isl_give isl_union_map *Scop::getWrites() { 1820 isl_union_map *Write = isl_union_map_empty(this->getParamSpace()); 1821 1822 for (ScopStmt *Stmt : *this) { 1823 for (MemoryAccess *MA : *Stmt) { 1824 if (!MA->isWrite()) 1825 continue; 1826 1827 isl_set *Domain = Stmt->getDomain(); 1828 isl_map *AccessDomain = MA->getAccessRelation(); 1829 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1830 Write = isl_union_map_add_map(Write, AccessDomain); 1831 } 1832 } 1833 return isl_union_map_coalesce(Write); 1834 } 1835 1836 __isl_give isl_union_map *Scop::getReads() { 1837 isl_union_map *Read = isl_union_map_empty(getParamSpace()); 1838 1839 for (ScopStmt *Stmt : *this) { 1840 for (MemoryAccess *MA : *Stmt) { 1841 if (!MA->isRead()) 1842 continue; 1843 1844 isl_set *Domain = Stmt->getDomain(); 1845 isl_map *AccessDomain = MA->getAccessRelation(); 1846 1847 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 1848 Read = isl_union_map_add_map(Read, AccessDomain); 1849 } 1850 } 1851 return isl_union_map_coalesce(Read); 1852 } 1853 1854 __isl_give isl_union_map *Scop::getSchedule() { 1855 isl_union_map *Schedule = isl_union_map_empty(getParamSpace()); 1856 1857 for (ScopStmt *Stmt : *this) 1858 Schedule = isl_union_map_add_map(Schedule, Stmt->getScattering()); 1859 1860 return isl_union_map_coalesce(Schedule); 1861 } 1862 1863 bool Scop::restrictDomains(__isl_take isl_union_set *Domain) { 1864 bool Changed = false; 1865 for (ScopStmt *Stmt : *this) { 1866 isl_union_set *StmtDomain = isl_union_set_from_set(Stmt->getDomain()); 1867 isl_union_set *NewStmtDomain = isl_union_set_intersect( 1868 isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain)); 1869 1870 if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) { 1871 isl_union_set_free(StmtDomain); 1872 isl_union_set_free(NewStmtDomain); 1873 continue; 1874 } 1875 1876 Changed = true; 1877 1878 isl_union_set_free(StmtDomain); 1879 NewStmtDomain = isl_union_set_coalesce(NewStmtDomain); 1880 1881 if (isl_union_set_is_empty(NewStmtDomain)) { 1882 Stmt->restrictDomain(isl_set_empty(Stmt->getDomainSpace())); 1883 isl_union_set_free(NewStmtDomain); 1884 } else 1885 Stmt->restrictDomain(isl_set_from_union_set(NewStmtDomain)); 1886 } 1887 isl_union_set_free(Domain); 1888 return Changed; 1889 } 1890 1891 ScalarEvolution *Scop::getSE() const { return SE; } 1892 1893 bool Scop::isTrivialBB(BasicBlock *BB, TempScop &tempScop) { 1894 if (tempScop.getAccessFunctions(BB)) 1895 return false; 1896 1897 return true; 1898 } 1899 1900 void Scop::addScopStmt(BasicBlock *BB, Region *R, TempScop &tempScop, 1901 const Region &CurRegion, 1902 SmallVectorImpl<Loop *> &NestLoops, 1903 SmallVectorImpl<unsigned> &Scatter) { 1904 ScopStmt *Stmt; 1905 1906 if (BB) { 1907 Stmt = new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter); 1908 StmtMap[BB] = Stmt; 1909 } else { 1910 assert(R && "Either a basic block or a region is needed to " 1911 "create a new SCoP stmt."); 1912 Stmt = new ScopStmt(*this, tempScop, CurRegion, *R, NestLoops, Scatter); 1913 for (BasicBlock *BB : R->blocks()) 1914 StmtMap[BB] = Stmt; 1915 } 1916 1917 // Insert all statements into the statement map and the statement vector. 1918 Stmts.push_back(Stmt); 1919 1920 // Increasing the Scattering function is OK for the moment, because 1921 // we are using a depth first iterator and the program is well structured. 1922 ++Scatter[NestLoops.size()]; 1923 } 1924 1925 void Scop::buildScop(TempScop &tempScop, const Region &CurRegion, 1926 SmallVectorImpl<Loop *> &NestLoops, 1927 SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI, 1928 ScopDetection &SD) { 1929 if (SD.isNonAffineSubRegion(&CurRegion, &getRegion())) 1930 return addScopStmt(nullptr, const_cast<Region *>(&CurRegion), tempScop, 1931 CurRegion, NestLoops, Scatter); 1932 1933 Loop *L = castToLoop(CurRegion, LI); 1934 1935 if (L) 1936 NestLoops.push_back(L); 1937 1938 unsigned loopDepth = NestLoops.size(); 1939 assert(Scatter.size() > loopDepth && "Scatter not big enough!"); 1940 1941 for (Region::const_element_iterator I = CurRegion.element_begin(), 1942 E = CurRegion.element_end(); 1943 I != E; ++I) 1944 if (I->isSubRegion()) { 1945 buildScop(tempScop, *I->getNodeAs<Region>(), NestLoops, Scatter, LI, SD); 1946 } else { 1947 BasicBlock *BB = I->getNodeAs<BasicBlock>(); 1948 1949 if (isTrivialBB(BB, tempScop)) 1950 continue; 1951 1952 addScopStmt(BB, nullptr, tempScop, CurRegion, NestLoops, Scatter); 1953 } 1954 1955 if (!L) 1956 return; 1957 1958 // Exiting a loop region. 1959 Scatter[loopDepth] = 0; 1960 NestLoops.pop_back(); 1961 ++Scatter[loopDepth - 1]; 1962 } 1963 1964 ScopStmt *Scop::getStmtForBasicBlock(BasicBlock *BB) const { 1965 const auto &StmtMapIt = StmtMap.find(BB); 1966 if (StmtMapIt == StmtMap.end()) 1967 return nullptr; 1968 return StmtMapIt->second; 1969 } 1970 1971 //===----------------------------------------------------------------------===// 1972 ScopInfo::ScopInfo() : RegionPass(ID), scop(0) { 1973 ctx = isl_ctx_alloc(); 1974 isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT); 1975 } 1976 1977 ScopInfo::~ScopInfo() { 1978 clear(); 1979 isl_ctx_free(ctx); 1980 } 1981 1982 void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const { 1983 AU.addRequired<LoopInfoWrapperPass>(); 1984 AU.addRequired<RegionInfoPass>(); 1985 AU.addRequired<ScalarEvolution>(); 1986 AU.addRequired<ScopDetection>(); 1987 AU.addRequired<TempScopInfo>(); 1988 AU.addRequired<AliasAnalysis>(); 1989 AU.setPreservesAll(); 1990 } 1991 1992 bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) { 1993 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 1994 AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); 1995 ScopDetection &SD = getAnalysis<ScopDetection>(); 1996 ScalarEvolution &SE = getAnalysis<ScalarEvolution>(); 1997 1998 TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R); 1999 2000 // This region is no Scop. 2001 if (!tempScop) { 2002 scop = nullptr; 2003 return false; 2004 } 2005 2006 scop = new Scop(*tempScop, LI, SE, SD, ctx); 2007 2008 if (!PollyUseRuntimeAliasChecks) { 2009 // Statistics. 2010 ++ScopFound; 2011 if (scop->getMaxLoopDepth() > 0) 2012 ++RichScopFound; 2013 return false; 2014 } 2015 2016 // If a problem occurs while building the alias groups we need to delete 2017 // this SCoP and pretend it wasn't valid in the first place. 2018 if (scop->buildAliasGroups(AA)) { 2019 // Statistics. 2020 ++ScopFound; 2021 if (scop->getMaxLoopDepth() > 0) 2022 ++RichScopFound; 2023 return false; 2024 } 2025 2026 DEBUG(dbgs() 2027 << "\n\nNOTE: Run time checks for " << scop->getNameStr() 2028 << " could not be created as the number of parameters involved is too " 2029 "high. The SCoP will be " 2030 "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust the " 2031 "maximal number of parameters but be advised that the compile time " 2032 "might increase exponentially.\n\n"); 2033 2034 delete scop; 2035 scop = nullptr; 2036 return false; 2037 } 2038 2039 char ScopInfo::ID = 0; 2040 2041 Pass *polly::createScopInfoPass() { return new ScopInfo(); } 2042 2043 INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops", 2044 "Polly - Create polyhedral description of Scops", false, 2045 false); 2046 INITIALIZE_AG_DEPENDENCY(AliasAnalysis); 2047 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 2048 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 2049 INITIALIZE_PASS_DEPENDENCY(ScalarEvolution); 2050 INITIALIZE_PASS_DEPENDENCY(ScopDetection); 2051 INITIALIZE_PASS_DEPENDENCY(TempScopInfo); 2052 INITIALIZE_PASS_END(ScopInfo, "polly-scops", 2053 "Polly - Create polyhedral description of Scops", false, 2054 false) 2055