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