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