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/ScopInfo.h" 21 #include "polly/LinkAllPasses.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 "llvm/ADT/DepthFirstIterator.h" 27 #include "llvm/ADT/MapVector.h" 28 #include "llvm/ADT/PostOrderIterator.h" 29 #include "llvm/ADT/STLExtras.h" 30 #include "llvm/ADT/SetVector.h" 31 #include "llvm/ADT/Statistic.h" 32 #include "llvm/ADT/StringExtras.h" 33 #include "llvm/Analysis/AliasAnalysis.h" 34 #include "llvm/Analysis/AssumptionCache.h" 35 #include "llvm/Analysis/LoopInfo.h" 36 #include "llvm/Analysis/LoopIterator.h" 37 #include "llvm/Analysis/RegionIterator.h" 38 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 39 #include "llvm/IR/DiagnosticInfo.h" 40 #include "llvm/Support/Debug.h" 41 #include "isl/aff.h" 42 #include "isl/constraint.h" 43 #include "isl/local_space.h" 44 #include "isl/map.h" 45 #include "isl/options.h" 46 #include "isl/printer.h" 47 #include "isl/schedule.h" 48 #include "isl/schedule_node.h" 49 #include "isl/set.h" 50 #include "isl/union_map.h" 51 #include "isl/union_set.h" 52 #include "isl/val.h" 53 #include <sstream> 54 #include <string> 55 #include <vector> 56 57 using namespace llvm; 58 using namespace polly; 59 60 #define DEBUG_TYPE "polly-scops" 61 62 STATISTIC(ScopFound, "Number of valid Scops"); 63 STATISTIC(RichScopFound, "Number of Scops containing a loop"); 64 65 // The maximal number of basic sets we allow during domain construction to 66 // be created. More complex scops will result in very high compile time and 67 // are also unlikely to result in good code 68 static int const MaxConjunctsInDomain = 20; 69 70 static cl::opt<bool> ModelReadOnlyScalars( 71 "polly-analyze-read-only-scalars", 72 cl::desc("Model read-only scalar values in the scop description"), 73 cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::cat(PollyCategory)); 74 75 // Multiplicative reductions can be disabled separately as these kind of 76 // operations can overflow easily. Additive reductions and bit operations 77 // are in contrast pretty stable. 78 static cl::opt<bool> DisableMultiplicativeReductions( 79 "polly-disable-multiplicative-reductions", 80 cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::ZeroOrMore, 81 cl::init(false), cl::cat(PollyCategory)); 82 83 static cl::opt<unsigned> RunTimeChecksMaxParameters( 84 "polly-rtc-max-parameters", 85 cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden, 86 cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory)); 87 88 static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup( 89 "polly-rtc-max-arrays-per-group", 90 cl::desc("The maximal number of arrays to compare in each alias group."), 91 cl::Hidden, cl::ZeroOrMore, cl::init(20), cl::cat(PollyCategory)); 92 static cl::opt<std::string> UserContextStr( 93 "polly-context", cl::value_desc("isl parameter set"), 94 cl::desc("Provide additional constraints on the context parameters"), 95 cl::init(""), cl::cat(PollyCategory)); 96 97 static cl::opt<bool> DetectReductions("polly-detect-reductions", 98 cl::desc("Detect and exploit reductions"), 99 cl::Hidden, cl::ZeroOrMore, 100 cl::init(true), cl::cat(PollyCategory)); 101 102 static cl::opt<int> MaxDisjunctsAssumed( 103 "polly-max-disjuncts-assumed", 104 cl::desc("The maximal number of disjuncts we allow in the assumption " 105 "context (this bounds compile time)"), 106 cl::Hidden, cl::ZeroOrMore, cl::init(150), cl::cat(PollyCategory)); 107 108 static cl::opt<bool> IgnoreIntegerWrapping( 109 "polly-ignore-integer-wrapping", 110 cl::desc("Do not build run-time checks to proof absence of integer " 111 "wrapping"), 112 cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); 113 114 //===----------------------------------------------------------------------===// 115 116 // Create a sequence of two schedules. Either argument may be null and is 117 // interpreted as the empty schedule. Can also return null if both schedules are 118 // empty. 119 static __isl_give isl_schedule * 120 combineInSequence(__isl_take isl_schedule *Prev, 121 __isl_take isl_schedule *Succ) { 122 if (!Prev) 123 return Succ; 124 if (!Succ) 125 return Prev; 126 127 return isl_schedule_sequence(Prev, Succ); 128 } 129 130 static __isl_give isl_set *addRangeBoundsToSet(__isl_take isl_set *S, 131 const ConstantRange &Range, 132 int dim, 133 enum isl_dim_type type) { 134 isl_val *V; 135 isl_ctx *ctx = isl_set_get_ctx(S); 136 137 bool useLowerUpperBound = Range.isSignWrappedSet() && !Range.isFullSet(); 138 const auto LB = useLowerUpperBound ? Range.getLower() : Range.getSignedMin(); 139 V = isl_valFromAPInt(ctx, LB, true); 140 isl_set *SLB = isl_set_lower_bound_val(isl_set_copy(S), type, dim, V); 141 142 const auto UB = useLowerUpperBound ? Range.getUpper() : Range.getSignedMax(); 143 V = isl_valFromAPInt(ctx, UB, true); 144 if (useLowerUpperBound) 145 V = isl_val_sub_ui(V, 1); 146 isl_set *SUB = isl_set_upper_bound_val(S, type, dim, V); 147 148 if (useLowerUpperBound) 149 return isl_set_union(SLB, SUB); 150 else 151 return isl_set_intersect(SLB, SUB); 152 } 153 154 static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) { 155 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr); 156 if (!BasePtrLI) 157 return nullptr; 158 159 if (!S->getRegion().contains(BasePtrLI)) 160 return nullptr; 161 162 ScalarEvolution &SE = *S->getSE(); 163 164 auto *OriginBaseSCEV = 165 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand())); 166 if (!OriginBaseSCEV) 167 return nullptr; 168 169 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV); 170 if (!OriginBaseSCEVUnknown) 171 return nullptr; 172 173 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(), 174 ScopArrayInfo::MK_Array); 175 } 176 177 ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx, 178 ArrayRef<const SCEV *> Sizes, enum MemoryKind Kind, 179 const DataLayout &DL, Scop *S) 180 : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) { 181 std::string BasePtrName = 182 getIslCompatibleName("MemRef_", BasePtr, Kind == MK_PHI ? "__phi" : ""); 183 Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this); 184 185 updateSizes(Sizes); 186 BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr); 187 if (BasePtrOriginSAI) 188 const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this); 189 } 190 191 __isl_give isl_space *ScopArrayInfo::getSpace() const { 192 auto *Space = 193 isl_space_set_alloc(isl_id_get_ctx(Id), 0, getNumberOfDimensions()); 194 Space = isl_space_set_tuple_id(Space, isl_dim_set, isl_id_copy(Id)); 195 return Space; 196 } 197 198 void ScopArrayInfo::updateElementType(Type *NewElementType) { 199 if (NewElementType == ElementType) 200 return; 201 202 auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType); 203 auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType); 204 205 if (NewElementSize == OldElementSize || NewElementSize == 0) 206 return; 207 208 if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) { 209 ElementType = NewElementType; 210 } else { 211 auto GCD = GreatestCommonDivisor64(NewElementSize, OldElementSize); 212 ElementType = IntegerType::get(ElementType->getContext(), GCD); 213 } 214 } 215 216 bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes) { 217 int SharedDims = std::min(NewSizes.size(), DimensionSizes.size()); 218 int ExtraDimsNew = NewSizes.size() - SharedDims; 219 int ExtraDimsOld = DimensionSizes.size() - SharedDims; 220 for (int i = 0; i < SharedDims; i++) 221 if (NewSizes[i + ExtraDimsNew] != DimensionSizes[i + ExtraDimsOld]) 222 return false; 223 224 if (DimensionSizes.size() >= NewSizes.size()) 225 return true; 226 227 DimensionSizes.clear(); 228 DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(), 229 NewSizes.end()); 230 for (isl_pw_aff *Size : DimensionSizesPw) 231 isl_pw_aff_free(Size); 232 DimensionSizesPw.clear(); 233 for (const SCEV *Expr : DimensionSizes) { 234 isl_pw_aff *Size = S.getPwAff(Expr); 235 DimensionSizesPw.push_back(Size); 236 } 237 return true; 238 } 239 240 ScopArrayInfo::~ScopArrayInfo() { 241 isl_id_free(Id); 242 for (isl_pw_aff *Size : DimensionSizesPw) 243 isl_pw_aff_free(Size); 244 } 245 246 std::string ScopArrayInfo::getName() const { return isl_id_get_name(Id); } 247 248 int ScopArrayInfo::getElemSizeInBytes() const { 249 return DL.getTypeAllocSize(ElementType); 250 } 251 252 isl_id *ScopArrayInfo::getBasePtrId() const { return isl_id_copy(Id); } 253 254 void ScopArrayInfo::dump() const { print(errs()); } 255 256 void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const { 257 OS.indent(8) << *getElementType() << " " << getName(); 258 if (getNumberOfDimensions() > 0) 259 OS << "[*]"; 260 for (unsigned u = 1; u < getNumberOfDimensions(); u++) { 261 OS << "["; 262 263 if (SizeAsPwAff) { 264 auto *Size = getDimensionSizePw(u); 265 OS << " " << Size << " "; 266 isl_pw_aff_free(Size); 267 } else { 268 OS << *getDimensionSize(u); 269 } 270 271 OS << "]"; 272 } 273 274 OS << ";"; 275 276 if (BasePtrOriginSAI) 277 OS << " [BasePtrOrigin: " << BasePtrOriginSAI->getName() << "]"; 278 279 OS << " // Element size " << getElemSizeInBytes() << "\n"; 280 } 281 282 const ScopArrayInfo * 283 ScopArrayInfo::getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA) { 284 isl_id *Id = isl_pw_multi_aff_get_tuple_id(PMA, isl_dim_out); 285 assert(Id && "Output dimension didn't have an ID"); 286 return getFromId(Id); 287 } 288 289 const ScopArrayInfo *ScopArrayInfo::getFromId(isl_id *Id) { 290 void *User = isl_id_get_user(Id); 291 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 292 isl_id_free(Id); 293 return SAI; 294 } 295 296 void MemoryAccess::updateDimensionality() { 297 auto *SAI = getScopArrayInfo(); 298 auto *ArraySpace = SAI->getSpace(); 299 auto *AccessSpace = isl_space_range(isl_map_get_space(AccessRelation)); 300 auto *Ctx = isl_space_get_ctx(AccessSpace); 301 302 auto DimsArray = isl_space_dim(ArraySpace, isl_dim_set); 303 auto DimsAccess = isl_space_dim(AccessSpace, isl_dim_set); 304 auto DimsMissing = DimsArray - DimsAccess; 305 306 auto *BB = getStatement()->getEntryBlock(); 307 auto &DL = BB->getModule()->getDataLayout(); 308 unsigned ArrayElemSize = SAI->getElemSizeInBytes(); 309 unsigned ElemBytes = DL.getTypeAllocSize(getElementType()); 310 311 auto *Map = isl_map_from_domain_and_range( 312 isl_set_universe(AccessSpace), 313 isl_set_universe(isl_space_copy(ArraySpace))); 314 315 for (unsigned i = 0; i < DimsMissing; i++) 316 Map = isl_map_fix_si(Map, isl_dim_out, i, 0); 317 318 for (unsigned i = DimsMissing; i < DimsArray; i++) 319 Map = isl_map_equate(Map, isl_dim_in, i - DimsMissing, isl_dim_out, i); 320 321 AccessRelation = isl_map_apply_range(AccessRelation, Map); 322 323 // For the non delinearized arrays, divide the access function of the last 324 // subscript by the size of the elements in the array. 325 // 326 // A stride one array access in C expressed as A[i] is expressed in 327 // LLVM-IR as something like A[i * elementsize]. This hides the fact that 328 // two subsequent values of 'i' index two values that are stored next to 329 // each other in memory. By this division we make this characteristic 330 // obvious again. If the base pointer was accessed with offsets not divisible 331 // by the accesses element size, we will have choosen a smaller ArrayElemSize 332 // that divides the offsets of all accesses to this base pointer. 333 if (DimsAccess == 1) { 334 isl_val *V = isl_val_int_from_si(Ctx, ArrayElemSize); 335 AccessRelation = isl_map_floordiv_val(AccessRelation, V); 336 } 337 338 if (!isAffine()) 339 computeBoundsOnAccessRelation(ArrayElemSize); 340 341 // Introduce multi-element accesses in case the type loaded by this memory 342 // access is larger than the canonical element type of the array. 343 // 344 // An access ((float *)A)[i] to an array char *A is modeled as 345 // {[i] -> A[o] : 4 i <= o <= 4 i + 3 346 if (ElemBytes > ArrayElemSize) { 347 assert(ElemBytes % ArrayElemSize == 0 && 348 "Loaded element size should be multiple of canonical element size"); 349 auto *Map = isl_map_from_domain_and_range( 350 isl_set_universe(isl_space_copy(ArraySpace)), 351 isl_set_universe(isl_space_copy(ArraySpace))); 352 for (unsigned i = 0; i < DimsArray - 1; i++) 353 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); 354 355 isl_constraint *C; 356 isl_local_space *LS; 357 358 LS = isl_local_space_from_space(isl_map_get_space(Map)); 359 int Num = ElemBytes / getScopArrayInfo()->getElemSizeInBytes(); 360 361 C = isl_constraint_alloc_inequality(isl_local_space_copy(LS)); 362 C = isl_constraint_set_constant_val(C, isl_val_int_from_si(Ctx, Num - 1)); 363 C = isl_constraint_set_coefficient_si(C, isl_dim_in, DimsArray - 1, 1); 364 C = isl_constraint_set_coefficient_si(C, isl_dim_out, DimsArray - 1, -1); 365 Map = isl_map_add_constraint(Map, C); 366 367 C = isl_constraint_alloc_inequality(LS); 368 C = isl_constraint_set_coefficient_si(C, isl_dim_in, DimsArray - 1, -1); 369 C = isl_constraint_set_coefficient_si(C, isl_dim_out, DimsArray - 1, 1); 370 C = isl_constraint_set_constant_val(C, isl_val_int_from_si(Ctx, 0)); 371 Map = isl_map_add_constraint(Map, C); 372 AccessRelation = isl_map_apply_range(AccessRelation, Map); 373 } 374 375 isl_space_free(ArraySpace); 376 377 assumeNoOutOfBound(); 378 } 379 380 const std::string 381 MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) { 382 switch (RT) { 383 case MemoryAccess::RT_NONE: 384 llvm_unreachable("Requested a reduction operator string for a memory " 385 "access which isn't a reduction"); 386 case MemoryAccess::RT_ADD: 387 return "+"; 388 case MemoryAccess::RT_MUL: 389 return "*"; 390 case MemoryAccess::RT_BOR: 391 return "|"; 392 case MemoryAccess::RT_BXOR: 393 return "^"; 394 case MemoryAccess::RT_BAND: 395 return "&"; 396 } 397 llvm_unreachable("Unknown reduction type"); 398 return ""; 399 } 400 401 /// @brief Return the reduction type for a given binary operator 402 static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp, 403 const Instruction *Load) { 404 if (!BinOp) 405 return MemoryAccess::RT_NONE; 406 switch (BinOp->getOpcode()) { 407 case Instruction::FAdd: 408 if (!BinOp->hasUnsafeAlgebra()) 409 return MemoryAccess::RT_NONE; 410 // Fall through 411 case Instruction::Add: 412 return MemoryAccess::RT_ADD; 413 case Instruction::Or: 414 return MemoryAccess::RT_BOR; 415 case Instruction::Xor: 416 return MemoryAccess::RT_BXOR; 417 case Instruction::And: 418 return MemoryAccess::RT_BAND; 419 case Instruction::FMul: 420 if (!BinOp->hasUnsafeAlgebra()) 421 return MemoryAccess::RT_NONE; 422 // Fall through 423 case Instruction::Mul: 424 if (DisableMultiplicativeReductions) 425 return MemoryAccess::RT_NONE; 426 return MemoryAccess::RT_MUL; 427 default: 428 return MemoryAccess::RT_NONE; 429 } 430 } 431 432 /// @brief Derive the individual index expressions from a GEP instruction 433 /// 434 /// This function optimistically assumes the GEP references into a fixed size 435 /// array. If this is actually true, this function returns a list of array 436 /// subscript expressions as SCEV as well as a list of integers describing 437 /// the size of the individual array dimensions. Both lists have either equal 438 /// length of the size list is one element shorter in case there is no known 439 /// size available for the outermost array dimension. 440 /// 441 /// @param GEP The GetElementPtr instruction to analyze. 442 /// 443 /// @return A tuple with the subscript expressions and the dimension sizes. 444 static std::tuple<std::vector<const SCEV *>, std::vector<int>> 445 getIndexExpressionsFromGEP(GetElementPtrInst *GEP, ScalarEvolution &SE) { 446 std::vector<const SCEV *> Subscripts; 447 std::vector<int> Sizes; 448 449 Type *Ty = GEP->getPointerOperandType(); 450 451 bool DroppedFirstDim = false; 452 453 for (unsigned i = 1; i < GEP->getNumOperands(); i++) { 454 455 const SCEV *Expr = SE.getSCEV(GEP->getOperand(i)); 456 457 if (i == 1) { 458 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) { 459 Ty = PtrTy->getElementType(); 460 } else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) { 461 Ty = ArrayTy->getElementType(); 462 } else { 463 Subscripts.clear(); 464 Sizes.clear(); 465 break; 466 } 467 if (auto *Const = dyn_cast<SCEVConstant>(Expr)) 468 if (Const->getValue()->isZero()) { 469 DroppedFirstDim = true; 470 continue; 471 } 472 Subscripts.push_back(Expr); 473 continue; 474 } 475 476 auto *ArrayTy = dyn_cast<ArrayType>(Ty); 477 if (!ArrayTy) { 478 Subscripts.clear(); 479 Sizes.clear(); 480 break; 481 } 482 483 Subscripts.push_back(Expr); 484 if (!(DroppedFirstDim && i == 2)) 485 Sizes.push_back(ArrayTy->getNumElements()); 486 487 Ty = ArrayTy->getElementType(); 488 } 489 490 return std::make_tuple(Subscripts, Sizes); 491 } 492 493 MemoryAccess::~MemoryAccess() { 494 isl_id_free(Id); 495 isl_map_free(AccessRelation); 496 isl_map_free(NewAccessRelation); 497 } 498 499 const ScopArrayInfo *MemoryAccess::getScopArrayInfo() const { 500 isl_id *ArrayId = getArrayId(); 501 void *User = isl_id_get_user(ArrayId); 502 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 503 isl_id_free(ArrayId); 504 return SAI; 505 } 506 507 __isl_give isl_id *MemoryAccess::getArrayId() const { 508 return isl_map_get_tuple_id(AccessRelation, isl_dim_out); 509 } 510 511 __isl_give isl_map *MemoryAccess::getAddressFunction() const { 512 return isl_map_lexmin(getAccessRelation()); 513 } 514 515 __isl_give isl_pw_multi_aff *MemoryAccess::applyScheduleToAccessRelation( 516 __isl_take isl_union_map *USchedule) const { 517 isl_map *Schedule, *ScheduledAccRel; 518 isl_union_set *UDomain; 519 520 UDomain = isl_union_set_from_set(getStatement()->getDomain()); 521 USchedule = isl_union_map_intersect_domain(USchedule, UDomain); 522 Schedule = isl_map_from_union_map(USchedule); 523 ScheduledAccRel = isl_map_apply_domain(getAddressFunction(), Schedule); 524 return isl_pw_multi_aff_from_map(ScheduledAccRel); 525 } 526 527 __isl_give isl_map *MemoryAccess::getOriginalAccessRelation() const { 528 return isl_map_copy(AccessRelation); 529 } 530 531 std::string MemoryAccess::getOriginalAccessRelationStr() const { 532 return stringFromIslObj(AccessRelation); 533 } 534 535 __isl_give isl_space *MemoryAccess::getOriginalAccessRelationSpace() const { 536 return isl_map_get_space(AccessRelation); 537 } 538 539 __isl_give isl_map *MemoryAccess::getNewAccessRelation() const { 540 return isl_map_copy(NewAccessRelation); 541 } 542 543 std::string MemoryAccess::getNewAccessRelationStr() const { 544 return stringFromIslObj(NewAccessRelation); 545 } 546 547 __isl_give isl_basic_map * 548 MemoryAccess::createBasicAccessMap(ScopStmt *Statement) { 549 isl_space *Space = isl_space_set_alloc(Statement->getIslCtx(), 0, 1); 550 Space = isl_space_align_params(Space, Statement->getDomainSpace()); 551 552 return isl_basic_map_from_domain_and_range( 553 isl_basic_set_universe(Statement->getDomainSpace()), 554 isl_basic_set_universe(Space)); 555 } 556 557 // Formalize no out-of-bound access assumption 558 // 559 // When delinearizing array accesses we optimistically assume that the 560 // delinearized accesses do not access out of bound locations (the subscript 561 // expression of each array evaluates for each statement instance that is 562 // executed to a value that is larger than zero and strictly smaller than the 563 // size of the corresponding dimension). The only exception is the outermost 564 // dimension for which we do not need to assume any upper bound. At this point 565 // we formalize this assumption to ensure that at code generation time the 566 // relevant run-time checks can be generated. 567 // 568 // To find the set of constraints necessary to avoid out of bound accesses, we 569 // first build the set of data locations that are not within array bounds. We 570 // then apply the reverse access relation to obtain the set of iterations that 571 // may contain invalid accesses and reduce this set of iterations to the ones 572 // that are actually executed by intersecting them with the domain of the 573 // statement. If we now project out all loop dimensions, we obtain a set of 574 // parameters that may cause statement instances to be executed that may 575 // possibly yield out of bound memory accesses. The complement of these 576 // constraints is the set of constraints that needs to be assumed to ensure such 577 // statement instances are never executed. 578 void MemoryAccess::assumeNoOutOfBound() { 579 auto *SAI = getScopArrayInfo(); 580 isl_space *Space = isl_space_range(getOriginalAccessRelationSpace()); 581 isl_set *Outside = isl_set_empty(isl_space_copy(Space)); 582 for (int i = 1, Size = isl_space_dim(Space, isl_dim_set); i < Size; ++i) { 583 isl_local_space *LS = isl_local_space_from_space(isl_space_copy(Space)); 584 isl_pw_aff *Var = 585 isl_pw_aff_var_on_domain(isl_local_space_copy(LS), isl_dim_set, i); 586 isl_pw_aff *Zero = isl_pw_aff_zero_on_domain(LS); 587 588 isl_set *DimOutside; 589 590 DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero); 591 isl_pw_aff *SizeE = SAI->getDimensionSizePw(i); 592 SizeE = isl_pw_aff_add_dims(SizeE, isl_dim_in, 593 isl_space_dim(Space, isl_dim_set)); 594 SizeE = isl_pw_aff_set_tuple_id(SizeE, isl_dim_in, 595 isl_space_get_tuple_id(Space, isl_dim_set)); 596 597 DimOutside = isl_set_union(DimOutside, isl_pw_aff_le_set(SizeE, Var)); 598 599 Outside = isl_set_union(Outside, DimOutside); 600 } 601 602 Outside = isl_set_apply(Outside, isl_map_reverse(getAccessRelation())); 603 Outside = isl_set_intersect(Outside, Statement->getDomain()); 604 Outside = isl_set_params(Outside); 605 606 // Remove divs to avoid the construction of overly complicated assumptions. 607 // Doing so increases the set of parameter combinations that are assumed to 608 // not appear. This is always save, but may make the resulting run-time check 609 // bail out more often than strictly necessary. 610 Outside = isl_set_remove_divs(Outside); 611 Outside = isl_set_complement(Outside); 612 Statement->getParent()->addAssumption( 613 INBOUNDS, Outside, 614 getAccessInstruction() ? getAccessInstruction()->getDebugLoc() : nullptr); 615 isl_space_free(Space); 616 } 617 618 void MemoryAccess::buildMemIntrinsicAccessRelation() { 619 assert(isa<MemIntrinsic>(getAccessInstruction())); 620 assert(Subscripts.size() == 2 && Sizes.size() == 0); 621 622 auto *SubscriptPWA = Statement->getPwAff(Subscripts[0]); 623 auto *SubscriptMap = isl_map_from_pw_aff(SubscriptPWA); 624 625 isl_map *LengthMap; 626 if (Subscripts[1] == nullptr) { 627 LengthMap = isl_map_universe(isl_map_get_space(SubscriptMap)); 628 } else { 629 auto *LengthPWA = Statement->getPwAff(Subscripts[1]); 630 LengthMap = isl_map_from_pw_aff(LengthPWA); 631 auto *RangeSpace = isl_space_range(isl_map_get_space(LengthMap)); 632 LengthMap = isl_map_apply_range(LengthMap, isl_map_lex_gt(RangeSpace)); 633 } 634 LengthMap = isl_map_lower_bound_si(LengthMap, isl_dim_out, 0, 0); 635 LengthMap = isl_map_align_params(LengthMap, isl_map_get_space(SubscriptMap)); 636 SubscriptMap = 637 isl_map_align_params(SubscriptMap, isl_map_get_space(LengthMap)); 638 LengthMap = isl_map_sum(LengthMap, SubscriptMap); 639 AccessRelation = isl_map_set_tuple_id(LengthMap, isl_dim_in, 640 getStatement()->getDomainId()); 641 } 642 643 void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) { 644 ScalarEvolution *SE = Statement->getParent()->getSE(); 645 646 auto MAI = MemAccInst(getAccessInstruction()); 647 if (isa<MemIntrinsic>(MAI)) 648 return; 649 650 Value *Ptr = MAI.getPointerOperand(); 651 if (!Ptr || !SE->isSCEVable(Ptr->getType())) 652 return; 653 654 auto *PtrSCEV = SE->getSCEV(Ptr); 655 if (isa<SCEVCouldNotCompute>(PtrSCEV)) 656 return; 657 658 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV); 659 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV)) 660 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV); 661 662 const ConstantRange &Range = SE->getSignedRange(PtrSCEV); 663 if (Range.isFullSet()) 664 return; 665 666 bool isWrapping = Range.isSignWrappedSet(); 667 unsigned BW = Range.getBitWidth(); 668 const auto One = APInt(BW, 1); 669 const auto LB = isWrapping ? Range.getLower() : Range.getSignedMin(); 670 const auto UB = isWrapping ? (Range.getUpper() - One) : Range.getSignedMax(); 671 672 auto Min = LB.sdiv(APInt(BW, ElementSize)); 673 auto Max = UB.sdiv(APInt(BW, ElementSize)) + One; 674 675 isl_set *AccessRange = isl_map_range(isl_map_copy(AccessRelation)); 676 AccessRange = 677 addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0, isl_dim_set); 678 AccessRelation = isl_map_intersect_range(AccessRelation, AccessRange); 679 } 680 681 __isl_give isl_map *MemoryAccess::foldAccess(__isl_take isl_map *AccessRelation, 682 ScopStmt *Statement) { 683 int Size = Subscripts.size(); 684 685 for (int i = Size - 2; i >= 0; --i) { 686 isl_space *Space; 687 isl_map *MapOne, *MapTwo; 688 isl_pw_aff *DimSize = Statement->getPwAff(Sizes[i]); 689 690 isl_space *SpaceSize = isl_pw_aff_get_space(DimSize); 691 isl_pw_aff_free(DimSize); 692 isl_id *ParamId = isl_space_get_dim_id(SpaceSize, isl_dim_param, 0); 693 694 Space = isl_map_get_space(AccessRelation); 695 Space = isl_space_map_from_set(isl_space_range(Space)); 696 Space = isl_space_align_params(Space, SpaceSize); 697 698 int ParamLocation = isl_space_find_dim_by_id(Space, isl_dim_param, ParamId); 699 isl_id_free(ParamId); 700 701 MapOne = isl_map_universe(isl_space_copy(Space)); 702 for (int j = 0; j < Size; ++j) 703 MapOne = isl_map_equate(MapOne, isl_dim_in, j, isl_dim_out, j); 704 MapOne = isl_map_lower_bound_si(MapOne, isl_dim_in, i + 1, 0); 705 706 MapTwo = isl_map_universe(isl_space_copy(Space)); 707 for (int j = 0; j < Size; ++j) 708 if (j < i || j > i + 1) 709 MapTwo = isl_map_equate(MapTwo, isl_dim_in, j, isl_dim_out, j); 710 711 isl_local_space *LS = isl_local_space_from_space(Space); 712 isl_constraint *C; 713 C = isl_equality_alloc(isl_local_space_copy(LS)); 714 C = isl_constraint_set_constant_si(C, -1); 715 C = isl_constraint_set_coefficient_si(C, isl_dim_in, i, 1); 716 C = isl_constraint_set_coefficient_si(C, isl_dim_out, i, -1); 717 MapTwo = isl_map_add_constraint(MapTwo, C); 718 C = isl_equality_alloc(LS); 719 C = isl_constraint_set_coefficient_si(C, isl_dim_in, i + 1, 1); 720 C = isl_constraint_set_coefficient_si(C, isl_dim_out, i + 1, -1); 721 C = isl_constraint_set_coefficient_si(C, isl_dim_param, ParamLocation, 1); 722 MapTwo = isl_map_add_constraint(MapTwo, C); 723 MapTwo = isl_map_upper_bound_si(MapTwo, isl_dim_in, i + 1, -1); 724 725 MapOne = isl_map_union(MapOne, MapTwo); 726 AccessRelation = isl_map_apply_range(AccessRelation, MapOne); 727 } 728 return AccessRelation; 729 } 730 731 /// @brief Check if @p Expr is divisible by @p Size. 732 static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) { 733 assert(Size != 0); 734 if (Size == 1) 735 return true; 736 737 // Only one factor needs to be divisible. 738 if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) { 739 for (auto *FactorExpr : MulExpr->operands()) 740 if (isDivisible(FactorExpr, Size, SE)) 741 return true; 742 return false; 743 } 744 745 // For other n-ary expressions (Add, AddRec, Max,...) all operands need 746 // to be divisble. 747 if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) { 748 for (auto *OpExpr : NAryExpr->operands()) 749 if (!isDivisible(OpExpr, Size, SE)) 750 return false; 751 return true; 752 } 753 754 auto *SizeSCEV = SE.getConstant(Expr->getType(), Size); 755 auto *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV); 756 auto *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV); 757 return MulSCEV == Expr; 758 } 759 760 void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) { 761 assert(!AccessRelation && "AccessReltation already built"); 762 763 isl_ctx *Ctx = isl_id_get_ctx(Id); 764 isl_id *BaseAddrId = SAI->getBasePtrId(); 765 766 if (!isAffine()) { 767 if (isa<MemIntrinsic>(getAccessInstruction())) 768 buildMemIntrinsicAccessRelation(); 769 770 // We overapproximate non-affine accesses with a possible access to the 771 // whole array. For read accesses it does not make a difference, if an 772 // access must or may happen. However, for write accesses it is important to 773 // differentiate between writes that must happen and writes that may happen. 774 if (!AccessRelation) 775 AccessRelation = isl_map_from_basic_map(createBasicAccessMap(Statement)); 776 777 AccessRelation = 778 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId); 779 return; 780 } 781 782 isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0); 783 AccessRelation = isl_map_universe(Space); 784 785 for (int i = 0, Size = Subscripts.size(); i < Size; ++i) { 786 isl_pw_aff *Affine = Statement->getPwAff(Subscripts[i]); 787 isl_map *SubscriptMap = isl_map_from_pw_aff(Affine); 788 AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap); 789 } 790 791 if (Sizes.size() >= 1 && !isa<SCEVConstant>(Sizes[0])) 792 AccessRelation = foldAccess(AccessRelation, Statement); 793 794 Space = Statement->getDomainSpace(); 795 AccessRelation = isl_map_set_tuple_id( 796 AccessRelation, isl_dim_in, isl_space_get_tuple_id(Space, isl_dim_set)); 797 AccessRelation = 798 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId); 799 800 AccessRelation = isl_map_gist_domain(AccessRelation, Statement->getDomain()); 801 isl_space_free(Space); 802 } 803 804 MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst, 805 AccessType AccType, Value *BaseAddress, 806 Type *ElementType, bool Affine, 807 ArrayRef<const SCEV *> Subscripts, 808 ArrayRef<const SCEV *> Sizes, Value *AccessValue, 809 ScopArrayInfo::MemoryKind Kind, StringRef BaseName) 810 : Kind(Kind), AccType(AccType), RedType(RT_NONE), Statement(Stmt), 811 BaseAddr(BaseAddress), BaseName(BaseName), ElementType(ElementType), 812 Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst), 813 AccessValue(AccessValue), IsAffine(Affine), 814 Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(nullptr), 815 NewAccessRelation(nullptr) { 816 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"}; 817 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size()) + "_"; 818 819 std::string IdName = 820 getIslCompatibleName(Stmt->getBaseName(), Access, BaseName); 821 Id = isl_id_alloc(Stmt->getParent()->getIslCtx(), IdName.c_str(), this); 822 } 823 824 void MemoryAccess::realignParams() { 825 isl_space *ParamSpace = Statement->getParent()->getParamSpace(); 826 AccessRelation = isl_map_align_params(AccessRelation, ParamSpace); 827 } 828 829 const std::string MemoryAccess::getReductionOperatorStr() const { 830 return MemoryAccess::getReductionOperatorStr(getReductionType()); 831 } 832 833 __isl_give isl_id *MemoryAccess::getId() const { return isl_id_copy(Id); } 834 835 raw_ostream &polly::operator<<(raw_ostream &OS, 836 MemoryAccess::ReductionType RT) { 837 if (RT == MemoryAccess::RT_NONE) 838 OS << "NONE"; 839 else 840 OS << MemoryAccess::getReductionOperatorStr(RT); 841 return OS; 842 } 843 844 void MemoryAccess::print(raw_ostream &OS) const { 845 switch (AccType) { 846 case READ: 847 OS.indent(12) << "ReadAccess :=\t"; 848 break; 849 case MUST_WRITE: 850 OS.indent(12) << "MustWriteAccess :=\t"; 851 break; 852 case MAY_WRITE: 853 OS.indent(12) << "MayWriteAccess :=\t"; 854 break; 855 } 856 OS << "[Reduction Type: " << getReductionType() << "] "; 857 OS << "[Scalar: " << isScalarKind() << "]\n"; 858 OS.indent(16) << getOriginalAccessRelationStr() << ";\n"; 859 if (hasNewAccessRelation()) 860 OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n"; 861 } 862 863 void MemoryAccess::dump() const { print(errs()); } 864 865 // Create a map in the size of the provided set domain, that maps from the 866 // one element of the provided set domain to another element of the provided 867 // set domain. 868 // The mapping is limited to all points that are equal in all but the last 869 // dimension and for which the last dimension of the input is strict smaller 870 // than the last dimension of the output. 871 // 872 // getEqualAndLarger(set[i0, i1, ..., iX]): 873 // 874 // set[i0, i1, ..., iX] -> set[o0, o1, ..., oX] 875 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX 876 // 877 static isl_map *getEqualAndLarger(isl_space *setDomain) { 878 isl_space *Space = isl_space_map_from_set(setDomain); 879 isl_map *Map = isl_map_universe(Space); 880 unsigned lastDimension = isl_map_dim(Map, isl_dim_in) - 1; 881 882 // Set all but the last dimension to be equal for the input and output 883 // 884 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX] 885 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1) 886 for (unsigned i = 0; i < lastDimension; ++i) 887 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); 888 889 // Set the last dimension of the input to be strict smaller than the 890 // last dimension of the output. 891 // 892 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX 893 Map = isl_map_order_lt(Map, isl_dim_in, lastDimension, isl_dim_out, 894 lastDimension); 895 return Map; 896 } 897 898 __isl_give isl_set * 899 MemoryAccess::getStride(__isl_take const isl_map *Schedule) const { 900 isl_map *S = const_cast<isl_map *>(Schedule); 901 isl_map *AccessRelation = getAccessRelation(); 902 isl_space *Space = isl_space_range(isl_map_get_space(S)); 903 isl_map *NextScatt = getEqualAndLarger(Space); 904 905 S = isl_map_reverse(S); 906 NextScatt = isl_map_lexmin(NextScatt); 907 908 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S)); 909 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation)); 910 NextScatt = isl_map_apply_domain(NextScatt, S); 911 NextScatt = isl_map_apply_domain(NextScatt, AccessRelation); 912 913 isl_set *Deltas = isl_map_deltas(NextScatt); 914 return Deltas; 915 } 916 917 bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule, 918 int StrideWidth) const { 919 isl_set *Stride, *StrideX; 920 bool IsStrideX; 921 922 Stride = getStride(Schedule); 923 StrideX = isl_set_universe(isl_set_get_space(Stride)); 924 for (unsigned i = 0; i < isl_set_dim(StrideX, isl_dim_set) - 1; i++) 925 StrideX = isl_set_fix_si(StrideX, isl_dim_set, i, 0); 926 StrideX = isl_set_fix_si(StrideX, isl_dim_set, 927 isl_set_dim(StrideX, isl_dim_set) - 1, StrideWidth); 928 IsStrideX = isl_set_is_subset(Stride, StrideX); 929 930 isl_set_free(StrideX); 931 isl_set_free(Stride); 932 933 return IsStrideX; 934 } 935 936 bool MemoryAccess::isStrideZero(const isl_map *Schedule) const { 937 return isStrideX(Schedule, 0); 938 } 939 940 bool MemoryAccess::isStrideOne(const isl_map *Schedule) const { 941 return isStrideX(Schedule, 1); 942 } 943 944 void MemoryAccess::setNewAccessRelation(isl_map *NewAccess) { 945 isl_map_free(NewAccessRelation); 946 NewAccessRelation = NewAccess; 947 } 948 949 //===----------------------------------------------------------------------===// 950 951 isl_map *ScopStmt::getSchedule() const { 952 isl_set *Domain = getDomain(); 953 if (isl_set_is_empty(Domain)) { 954 isl_set_free(Domain); 955 return isl_map_from_aff( 956 isl_aff_zero_on_domain(isl_local_space_from_space(getDomainSpace()))); 957 } 958 auto *Schedule = getParent()->getSchedule(); 959 Schedule = isl_union_map_intersect_domain( 960 Schedule, isl_union_set_from_set(isl_set_copy(Domain))); 961 if (isl_union_map_is_empty(Schedule)) { 962 isl_set_free(Domain); 963 isl_union_map_free(Schedule); 964 return isl_map_from_aff( 965 isl_aff_zero_on_domain(isl_local_space_from_space(getDomainSpace()))); 966 } 967 auto *M = isl_map_from_union_map(Schedule); 968 M = isl_map_coalesce(M); 969 M = isl_map_gist_domain(M, Domain); 970 M = isl_map_coalesce(M); 971 return M; 972 } 973 974 __isl_give isl_pw_aff *ScopStmt::getPwAff(const SCEV *E) { 975 return getParent()->getPwAff(E, getEntryBlock()); 976 } 977 978 void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) { 979 assert(isl_set_is_subset(NewDomain, Domain) && 980 "New domain is not a subset of old domain!"); 981 isl_set_free(Domain); 982 Domain = NewDomain; 983 } 984 985 void ScopStmt::buildAccessRelations() { 986 Scop &S = *getParent(); 987 for (MemoryAccess *Access : MemAccs) { 988 Type *ElementType = Access->getElementType(); 989 990 ScopArrayInfo::MemoryKind Ty; 991 if (Access->isPHIKind()) 992 Ty = ScopArrayInfo::MK_PHI; 993 else if (Access->isExitPHIKind()) 994 Ty = ScopArrayInfo::MK_ExitPHI; 995 else if (Access->isValueKind()) 996 Ty = ScopArrayInfo::MK_Value; 997 else 998 Ty = ScopArrayInfo::MK_Array; 999 1000 auto *SAI = S.getOrCreateScopArrayInfo(Access->getBaseAddr(), ElementType, 1001 Access->Sizes, Ty); 1002 Access->buildAccessRelation(SAI); 1003 } 1004 } 1005 1006 void ScopStmt::addAccess(MemoryAccess *Access) { 1007 Instruction *AccessInst = Access->getAccessInstruction(); 1008 1009 if (Access->isArrayKind()) { 1010 MemoryAccessList &MAL = InstructionToAccess[AccessInst]; 1011 MAL.emplace_front(Access); 1012 } else if (Access->isValueKind() && Access->isWrite()) { 1013 Instruction *AccessVal = cast<Instruction>(Access->getAccessValue()); 1014 assert(Parent.getStmtFor(AccessVal) == this); 1015 assert(!ValueWrites.lookup(AccessVal)); 1016 1017 ValueWrites[AccessVal] = Access; 1018 } else if (Access->isValueKind() && Access->isRead()) { 1019 Value *AccessVal = Access->getAccessValue(); 1020 assert(!ValueReads.lookup(AccessVal)); 1021 1022 ValueReads[AccessVal] = Access; 1023 } else if (Access->isAnyPHIKind() && Access->isWrite()) { 1024 PHINode *PHI = cast<PHINode>(Access->getBaseAddr()); 1025 assert(!PHIWrites.lookup(PHI)); 1026 1027 PHIWrites[PHI] = Access; 1028 } 1029 1030 MemAccs.push_back(Access); 1031 } 1032 1033 void ScopStmt::realignParams() { 1034 for (MemoryAccess *MA : *this) 1035 MA->realignParams(); 1036 1037 Domain = isl_set_align_params(Domain, Parent.getParamSpace()); 1038 } 1039 1040 /// @brief Add @p BSet to the set @p User if @p BSet is bounded. 1041 static isl_stat collectBoundedParts(__isl_take isl_basic_set *BSet, 1042 void *User) { 1043 isl_set **BoundedParts = static_cast<isl_set **>(User); 1044 if (isl_basic_set_is_bounded(BSet)) 1045 *BoundedParts = isl_set_union(*BoundedParts, isl_set_from_basic_set(BSet)); 1046 else 1047 isl_basic_set_free(BSet); 1048 return isl_stat_ok; 1049 } 1050 1051 /// @brief Return the bounded parts of @p S. 1052 static __isl_give isl_set *collectBoundedParts(__isl_take isl_set *S) { 1053 isl_set *BoundedParts = isl_set_empty(isl_set_get_space(S)); 1054 isl_set_foreach_basic_set(S, collectBoundedParts, &BoundedParts); 1055 isl_set_free(S); 1056 return BoundedParts; 1057 } 1058 1059 /// @brief Compute the (un)bounded parts of @p S wrt. to dimension @p Dim. 1060 /// 1061 /// @returns A separation of @p S into first an unbounded then a bounded subset, 1062 /// both with regards to the dimension @p Dim. 1063 static std::pair<__isl_give isl_set *, __isl_give isl_set *> 1064 partitionSetParts(__isl_take isl_set *S, unsigned Dim) { 1065 1066 for (unsigned u = 0, e = isl_set_n_dim(S); u < e; u++) 1067 S = isl_set_lower_bound_si(S, isl_dim_set, u, 0); 1068 1069 unsigned NumDimsS = isl_set_n_dim(S); 1070 isl_set *OnlyDimS = isl_set_copy(S); 1071 1072 // Remove dimensions that are greater than Dim as they are not interesting. 1073 assert(NumDimsS >= Dim + 1); 1074 OnlyDimS = 1075 isl_set_project_out(OnlyDimS, isl_dim_set, Dim + 1, NumDimsS - Dim - 1); 1076 1077 // Create artificial parametric upper bounds for dimensions smaller than Dim 1078 // as we are not interested in them. 1079 OnlyDimS = isl_set_insert_dims(OnlyDimS, isl_dim_param, 0, Dim); 1080 for (unsigned u = 0; u < Dim; u++) { 1081 isl_constraint *C = isl_inequality_alloc( 1082 isl_local_space_from_space(isl_set_get_space(OnlyDimS))); 1083 C = isl_constraint_set_coefficient_si(C, isl_dim_param, u, 1); 1084 C = isl_constraint_set_coefficient_si(C, isl_dim_set, u, -1); 1085 OnlyDimS = isl_set_add_constraint(OnlyDimS, C); 1086 } 1087 1088 // Collect all bounded parts of OnlyDimS. 1089 isl_set *BoundedParts = collectBoundedParts(OnlyDimS); 1090 1091 // Create the dimensions greater than Dim again. 1092 BoundedParts = isl_set_insert_dims(BoundedParts, isl_dim_set, Dim + 1, 1093 NumDimsS - Dim - 1); 1094 1095 // Remove the artificial upper bound parameters again. 1096 BoundedParts = isl_set_remove_dims(BoundedParts, isl_dim_param, 0, Dim); 1097 1098 isl_set *UnboundedParts = isl_set_subtract(S, isl_set_copy(BoundedParts)); 1099 return std::make_pair(UnboundedParts, BoundedParts); 1100 } 1101 1102 /// @brief Set the dimension Ids from @p From in @p To. 1103 static __isl_give isl_set *setDimensionIds(__isl_keep isl_set *From, 1104 __isl_take isl_set *To) { 1105 for (unsigned u = 0, e = isl_set_n_dim(From); u < e; u++) { 1106 isl_id *DimId = isl_set_get_dim_id(From, isl_dim_set, u); 1107 To = isl_set_set_dim_id(To, isl_dim_set, u, DimId); 1108 } 1109 return To; 1110 } 1111 1112 /// @brief Create the conditions under which @p L @p Pred @p R is true. 1113 static __isl_give isl_set *buildConditionSet(ICmpInst::Predicate Pred, 1114 __isl_take isl_pw_aff *L, 1115 __isl_take isl_pw_aff *R) { 1116 switch (Pred) { 1117 case ICmpInst::ICMP_EQ: 1118 return isl_pw_aff_eq_set(L, R); 1119 case ICmpInst::ICMP_NE: 1120 return isl_pw_aff_ne_set(L, R); 1121 case ICmpInst::ICMP_SLT: 1122 return isl_pw_aff_lt_set(L, R); 1123 case ICmpInst::ICMP_SLE: 1124 return isl_pw_aff_le_set(L, R); 1125 case ICmpInst::ICMP_SGT: 1126 return isl_pw_aff_gt_set(L, R); 1127 case ICmpInst::ICMP_SGE: 1128 return isl_pw_aff_ge_set(L, R); 1129 case ICmpInst::ICMP_ULT: 1130 return isl_pw_aff_lt_set(L, R); 1131 case ICmpInst::ICMP_UGT: 1132 return isl_pw_aff_gt_set(L, R); 1133 case ICmpInst::ICMP_ULE: 1134 return isl_pw_aff_le_set(L, R); 1135 case ICmpInst::ICMP_UGE: 1136 return isl_pw_aff_ge_set(L, R); 1137 default: 1138 llvm_unreachable("Non integer predicate not supported"); 1139 } 1140 } 1141 1142 /// @brief Create the conditions under which @p L @p Pred @p R is true. 1143 /// 1144 /// Helper function that will make sure the dimensions of the result have the 1145 /// same isl_id's as the @p Domain. 1146 static __isl_give isl_set *buildConditionSet(ICmpInst::Predicate Pred, 1147 __isl_take isl_pw_aff *L, 1148 __isl_take isl_pw_aff *R, 1149 __isl_keep isl_set *Domain) { 1150 isl_set *ConsequenceCondSet = buildConditionSet(Pred, L, R); 1151 return setDimensionIds(Domain, ConsequenceCondSet); 1152 } 1153 1154 /// @brief Build the conditions sets for the switch @p SI in the @p Domain. 1155 /// 1156 /// This will fill @p ConditionSets with the conditions under which control 1157 /// will be moved from @p SI to its successors. Hence, @p ConditionSets will 1158 /// have as many elements as @p SI has successors. 1159 static void 1160 buildConditionSets(Scop &S, SwitchInst *SI, Loop *L, __isl_keep isl_set *Domain, 1161 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) { 1162 1163 Value *Condition = getConditionFromTerminator(SI); 1164 assert(Condition && "No condition for switch"); 1165 1166 ScalarEvolution &SE = *S.getSE(); 1167 BasicBlock *BB = SI->getParent(); 1168 isl_pw_aff *LHS, *RHS; 1169 LHS = S.getPwAff(SE.getSCEVAtScope(Condition, L), BB); 1170 1171 unsigned NumSuccessors = SI->getNumSuccessors(); 1172 ConditionSets.resize(NumSuccessors); 1173 for (auto &Case : SI->cases()) { 1174 unsigned Idx = Case.getSuccessorIndex(); 1175 ConstantInt *CaseValue = Case.getCaseValue(); 1176 1177 RHS = S.getPwAff(SE.getSCEV(CaseValue), BB); 1178 isl_set *CaseConditionSet = 1179 buildConditionSet(ICmpInst::ICMP_EQ, isl_pw_aff_copy(LHS), RHS, Domain); 1180 ConditionSets[Idx] = isl_set_coalesce( 1181 isl_set_intersect(CaseConditionSet, isl_set_copy(Domain))); 1182 } 1183 1184 assert(ConditionSets[0] == nullptr && "Default condition set was set"); 1185 isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]); 1186 for (unsigned u = 2; u < NumSuccessors; u++) 1187 ConditionSetUnion = 1188 isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u])); 1189 ConditionSets[0] = setDimensionIds( 1190 Domain, isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion)); 1191 1192 S.markAsOptimized(); 1193 isl_pw_aff_free(LHS); 1194 } 1195 1196 /// @brief Build the conditions sets for the branch condition @p Condition in 1197 /// the @p Domain. 1198 /// 1199 /// This will fill @p ConditionSets with the conditions under which control 1200 /// will be moved from @p TI to its successors. Hence, @p ConditionSets will 1201 /// have as many elements as @p TI has successors. If @p TI is nullptr the 1202 /// context under which @p Condition is true/false will be returned as the 1203 /// new elements of @p ConditionSets. 1204 static void 1205 buildConditionSets(Scop &S, Value *Condition, TerminatorInst *TI, Loop *L, 1206 __isl_keep isl_set *Domain, 1207 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) { 1208 1209 isl_set *ConsequenceCondSet = nullptr; 1210 if (auto *CCond = dyn_cast<ConstantInt>(Condition)) { 1211 if (CCond->isZero()) 1212 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain)); 1213 else 1214 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain)); 1215 } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) { 1216 auto Opcode = BinOp->getOpcode(); 1217 assert(Opcode == Instruction::And || Opcode == Instruction::Or); 1218 1219 buildConditionSets(S, BinOp->getOperand(0), TI, L, Domain, ConditionSets); 1220 buildConditionSets(S, BinOp->getOperand(1), TI, L, Domain, ConditionSets); 1221 1222 isl_set_free(ConditionSets.pop_back_val()); 1223 isl_set *ConsCondPart0 = ConditionSets.pop_back_val(); 1224 isl_set_free(ConditionSets.pop_back_val()); 1225 isl_set *ConsCondPart1 = ConditionSets.pop_back_val(); 1226 1227 if (Opcode == Instruction::And) 1228 ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1); 1229 else 1230 ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1); 1231 } else { 1232 auto *ICond = dyn_cast<ICmpInst>(Condition); 1233 assert(ICond && 1234 "Condition of exiting branch was neither constant nor ICmp!"); 1235 1236 ScalarEvolution &SE = *S.getSE(); 1237 BasicBlock *BB = TI ? TI->getParent() : nullptr; 1238 isl_pw_aff *LHS, *RHS; 1239 LHS = S.getPwAff(SE.getSCEVAtScope(ICond->getOperand(0), L), BB); 1240 RHS = S.getPwAff(SE.getSCEVAtScope(ICond->getOperand(1), L), BB); 1241 ConsequenceCondSet = 1242 buildConditionSet(ICond->getPredicate(), LHS, RHS, Domain); 1243 } 1244 1245 // If no terminator was given we are only looking for parameter constraints 1246 // under which @p Condition is true/false. 1247 if (!TI) 1248 ConsequenceCondSet = isl_set_params(ConsequenceCondSet); 1249 1250 assert(ConsequenceCondSet); 1251 isl_set *AlternativeCondSet = 1252 isl_set_complement(isl_set_copy(ConsequenceCondSet)); 1253 1254 ConditionSets.push_back(isl_set_coalesce( 1255 isl_set_intersect(ConsequenceCondSet, isl_set_copy(Domain)))); 1256 ConditionSets.push_back(isl_set_coalesce( 1257 isl_set_intersect(AlternativeCondSet, isl_set_copy(Domain)))); 1258 } 1259 1260 /// @brief Build the conditions sets for the terminator @p TI in the @p Domain. 1261 /// 1262 /// This will fill @p ConditionSets with the conditions under which control 1263 /// will be moved from @p TI to its successors. Hence, @p ConditionSets will 1264 /// have as many elements as @p TI has successors. 1265 static void 1266 buildConditionSets(Scop &S, TerminatorInst *TI, Loop *L, 1267 __isl_keep isl_set *Domain, 1268 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) { 1269 1270 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) 1271 return buildConditionSets(S, SI, L, Domain, ConditionSets); 1272 1273 assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch."); 1274 1275 if (TI->getNumSuccessors() == 1) { 1276 ConditionSets.push_back(isl_set_copy(Domain)); 1277 return; 1278 } 1279 1280 Value *Condition = getConditionFromTerminator(TI); 1281 assert(Condition && "No condition for Terminator"); 1282 1283 return buildConditionSets(S, Condition, TI, L, Domain, ConditionSets); 1284 } 1285 1286 void ScopStmt::buildDomain() { 1287 isl_id *Id = isl_id_alloc(getIslCtx(), getBaseName(), this); 1288 1289 Domain = getParent()->getDomainConditions(this); 1290 Domain = isl_set_set_tuple_id(Domain, Id); 1291 } 1292 1293 void ScopStmt::deriveAssumptionsFromGEP(GetElementPtrInst *GEP, 1294 ScopDetection &SD) { 1295 isl_ctx *Ctx = Parent.getIslCtx(); 1296 isl_local_space *LSpace = isl_local_space_from_space(getDomainSpace()); 1297 Type *Ty = GEP->getPointerOperandType(); 1298 ScalarEvolution &SE = *Parent.getSE(); 1299 1300 // The set of loads that are required to be invariant. 1301 auto &ScopRIL = *SD.getRequiredInvariantLoads(&Parent.getRegion()); 1302 1303 std::vector<const SCEV *> Subscripts; 1304 std::vector<int> Sizes; 1305 1306 std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP, SE); 1307 1308 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) { 1309 Ty = PtrTy->getElementType(); 1310 } 1311 1312 int IndexOffset = Subscripts.size() - Sizes.size(); 1313 1314 assert(IndexOffset <= 1 && "Unexpected large index offset"); 1315 1316 for (size_t i = 0; i < Sizes.size(); i++) { 1317 auto *Expr = Subscripts[i + IndexOffset]; 1318 auto Size = Sizes[i]; 1319 1320 InvariantLoadsSetTy AccessILS; 1321 if (!isAffineExpr(&Parent.getRegion(), Expr, SE, nullptr, &AccessILS)) 1322 continue; 1323 1324 bool NonAffine = false; 1325 for (LoadInst *LInst : AccessILS) 1326 if (!ScopRIL.count(LInst)) 1327 NonAffine = true; 1328 1329 if (NonAffine) 1330 continue; 1331 1332 isl_pw_aff *AccessOffset = getPwAff(Expr); 1333 AccessOffset = 1334 isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId()); 1335 1336 isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain( 1337 isl_local_space_copy(LSpace), isl_val_int_from_si(Ctx, Size))); 1338 1339 isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize); 1340 OutOfBound = isl_set_intersect(getDomain(), OutOfBound); 1341 OutOfBound = isl_set_params(OutOfBound); 1342 isl_set *InBound = isl_set_complement(OutOfBound); 1343 isl_set *Executed = isl_set_params(getDomain()); 1344 1345 // A => B == !A or B 1346 isl_set *InBoundIfExecuted = 1347 isl_set_union(isl_set_complement(Executed), InBound); 1348 1349 InBoundIfExecuted = isl_set_coalesce(InBoundIfExecuted); 1350 Parent.addAssumption(INBOUNDS, InBoundIfExecuted, GEP->getDebugLoc()); 1351 } 1352 1353 isl_local_space_free(LSpace); 1354 } 1355 1356 void ScopStmt::deriveAssumptions(BasicBlock *Block, ScopDetection &SD) { 1357 for (Instruction &Inst : *Block) 1358 if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst)) 1359 deriveAssumptionsFromGEP(GEP, SD); 1360 } 1361 1362 void ScopStmt::collectSurroundingLoops() { 1363 for (unsigned u = 0, e = isl_set_n_dim(Domain); u < e; u++) { 1364 isl_id *DimId = isl_set_get_dim_id(Domain, isl_dim_set, u); 1365 NestLoops.push_back(static_cast<Loop *>(isl_id_get_user(DimId))); 1366 isl_id_free(DimId); 1367 } 1368 } 1369 1370 ScopStmt::ScopStmt(Scop &parent, Region &R) 1371 : Parent(parent), Domain(nullptr), BB(nullptr), R(&R), Build(nullptr) { 1372 1373 BaseName = getIslCompatibleName("Stmt_", R.getNameStr(), ""); 1374 } 1375 1376 ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb) 1377 : Parent(parent), Domain(nullptr), BB(&bb), R(nullptr), Build(nullptr) { 1378 1379 BaseName = getIslCompatibleName("Stmt_", &bb, ""); 1380 } 1381 1382 void ScopStmt::init(ScopDetection &SD) { 1383 assert(!Domain && "init must be called only once"); 1384 1385 buildDomain(); 1386 collectSurroundingLoops(); 1387 buildAccessRelations(); 1388 1389 if (BB) { 1390 deriveAssumptions(BB, SD); 1391 } else { 1392 for (BasicBlock *Block : R->blocks()) { 1393 deriveAssumptions(Block, SD); 1394 } 1395 } 1396 1397 if (DetectReductions) 1398 checkForReductions(); 1399 } 1400 1401 /// @brief Collect loads which might form a reduction chain with @p StoreMA 1402 /// 1403 /// Check if the stored value for @p StoreMA is a binary operator with one or 1404 /// two loads as operands. If the binary operand is commutative & associative, 1405 /// used only once (by @p StoreMA) and its load operands are also used only 1406 /// once, we have found a possible reduction chain. It starts at an operand 1407 /// load and includes the binary operator and @p StoreMA. 1408 /// 1409 /// Note: We allow only one use to ensure the load and binary operator cannot 1410 /// escape this block or into any other store except @p StoreMA. 1411 void ScopStmt::collectCandiateReductionLoads( 1412 MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) { 1413 auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction()); 1414 if (!Store) 1415 return; 1416 1417 // Skip if there is not one binary operator between the load and the store 1418 auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand()); 1419 if (!BinOp) 1420 return; 1421 1422 // Skip if the binary operators has multiple uses 1423 if (BinOp->getNumUses() != 1) 1424 return; 1425 1426 // Skip if the opcode of the binary operator is not commutative/associative 1427 if (!BinOp->isCommutative() || !BinOp->isAssociative()) 1428 return; 1429 1430 // Skip if the binary operator is outside the current SCoP 1431 if (BinOp->getParent() != Store->getParent()) 1432 return; 1433 1434 // Skip if it is a multiplicative reduction and we disabled them 1435 if (DisableMultiplicativeReductions && 1436 (BinOp->getOpcode() == Instruction::Mul || 1437 BinOp->getOpcode() == Instruction::FMul)) 1438 return; 1439 1440 // Check the binary operator operands for a candidate load 1441 auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0)); 1442 auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1)); 1443 if (!PossibleLoad0 && !PossibleLoad1) 1444 return; 1445 1446 // A load is only a candidate if it cannot escape (thus has only this use) 1447 if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1) 1448 if (PossibleLoad0->getParent() == Store->getParent()) 1449 Loads.push_back(&getArrayAccessFor(PossibleLoad0)); 1450 if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1) 1451 if (PossibleLoad1->getParent() == Store->getParent()) 1452 Loads.push_back(&getArrayAccessFor(PossibleLoad1)); 1453 } 1454 1455 /// @brief Check for reductions in this ScopStmt 1456 /// 1457 /// Iterate over all store memory accesses and check for valid binary reduction 1458 /// like chains. For all candidates we check if they have the same base address 1459 /// and there are no other accesses which overlap with them. The base address 1460 /// check rules out impossible reductions candidates early. The overlap check, 1461 /// together with the "only one user" check in collectCandiateReductionLoads, 1462 /// guarantees that none of the intermediate results will escape during 1463 /// execution of the loop nest. We basically check here that no other memory 1464 /// access can access the same memory as the potential reduction. 1465 void ScopStmt::checkForReductions() { 1466 SmallVector<MemoryAccess *, 2> Loads; 1467 SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates; 1468 1469 // First collect candidate load-store reduction chains by iterating over all 1470 // stores and collecting possible reduction loads. 1471 for (MemoryAccess *StoreMA : MemAccs) { 1472 if (StoreMA->isRead()) 1473 continue; 1474 1475 Loads.clear(); 1476 collectCandiateReductionLoads(StoreMA, Loads); 1477 for (MemoryAccess *LoadMA : Loads) 1478 Candidates.push_back(std::make_pair(LoadMA, StoreMA)); 1479 } 1480 1481 // Then check each possible candidate pair. 1482 for (const auto &CandidatePair : Candidates) { 1483 bool Valid = true; 1484 isl_map *LoadAccs = CandidatePair.first->getAccessRelation(); 1485 isl_map *StoreAccs = CandidatePair.second->getAccessRelation(); 1486 1487 // Skip those with obviously unequal base addresses. 1488 if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) { 1489 isl_map_free(LoadAccs); 1490 isl_map_free(StoreAccs); 1491 continue; 1492 } 1493 1494 // And check if the remaining for overlap with other memory accesses. 1495 isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs); 1496 AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain()); 1497 isl_set *AllAccs = isl_map_range(AllAccsRel); 1498 1499 for (MemoryAccess *MA : MemAccs) { 1500 if (MA == CandidatePair.first || MA == CandidatePair.second) 1501 continue; 1502 1503 isl_map *AccRel = 1504 isl_map_intersect_domain(MA->getAccessRelation(), getDomain()); 1505 isl_set *Accs = isl_map_range(AccRel); 1506 1507 if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) { 1508 isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs)); 1509 Valid = Valid && isl_set_is_empty(OverlapAccs); 1510 isl_set_free(OverlapAccs); 1511 } 1512 } 1513 1514 isl_set_free(AllAccs); 1515 if (!Valid) 1516 continue; 1517 1518 const LoadInst *Load = 1519 dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction()); 1520 MemoryAccess::ReductionType RT = 1521 getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load); 1522 1523 // If no overlapping access was found we mark the load and store as 1524 // reduction like. 1525 CandidatePair.first->markAsReductionLike(RT); 1526 CandidatePair.second->markAsReductionLike(RT); 1527 } 1528 } 1529 1530 std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); } 1531 1532 std::string ScopStmt::getScheduleStr() const { 1533 auto *S = getSchedule(); 1534 auto Str = stringFromIslObj(S); 1535 isl_map_free(S); 1536 return Str; 1537 } 1538 1539 BasicBlock *ScopStmt::getEntryBlock() const { 1540 if (isBlockStmt()) 1541 return getBasicBlock(); 1542 return getRegion()->getEntry(); 1543 } 1544 1545 RegionNode *ScopStmt::getRegionNode() const { 1546 if (isRegionStmt()) 1547 return getRegion()->getNode(); 1548 return getParent()->getRegion().getBBNode(getBasicBlock()); 1549 } 1550 1551 unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); } 1552 1553 unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); } 1554 1555 const char *ScopStmt::getBaseName() const { return BaseName.c_str(); } 1556 1557 const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const { 1558 return NestLoops[Dimension]; 1559 } 1560 1561 isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); } 1562 1563 __isl_give isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); } 1564 1565 __isl_give isl_space *ScopStmt::getDomainSpace() const { 1566 return isl_set_get_space(Domain); 1567 } 1568 1569 __isl_give isl_id *ScopStmt::getDomainId() const { 1570 return isl_set_get_tuple_id(Domain); 1571 } 1572 1573 ScopStmt::~ScopStmt() { isl_set_free(Domain); } 1574 1575 void ScopStmt::print(raw_ostream &OS) const { 1576 OS << "\t" << getBaseName() << "\n"; 1577 OS.indent(12) << "Domain :=\n"; 1578 1579 if (Domain) { 1580 OS.indent(16) << getDomainStr() << ";\n"; 1581 } else 1582 OS.indent(16) << "n/a\n"; 1583 1584 OS.indent(12) << "Schedule :=\n"; 1585 1586 if (Domain) { 1587 OS.indent(16) << getScheduleStr() << ";\n"; 1588 } else 1589 OS.indent(16) << "n/a\n"; 1590 1591 for (MemoryAccess *Access : MemAccs) 1592 Access->print(OS); 1593 } 1594 1595 void ScopStmt::dump() const { print(dbgs()); } 1596 1597 void ScopStmt::removeMemoryAccesses(MemoryAccessList &InvMAs) { 1598 // Remove all memory accesses in @p InvMAs from this statement 1599 // together with all scalar accesses that were caused by them. 1600 // MK_Value READs have no access instruction, hence would not be removed by 1601 // this function. However, it is only used for invariant LoadInst accesses, 1602 // its arguments are always affine, hence synthesizable, and therefore there 1603 // are no MK_Value READ accesses to be removed. 1604 for (MemoryAccess *MA : InvMAs) { 1605 auto Predicate = [&](MemoryAccess *Acc) { 1606 return Acc->getAccessInstruction() == MA->getAccessInstruction(); 1607 }; 1608 MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate), 1609 MemAccs.end()); 1610 InstructionToAccess.erase(MA->getAccessInstruction()); 1611 } 1612 } 1613 1614 //===----------------------------------------------------------------------===// 1615 /// Scop class implement 1616 1617 void Scop::setContext(__isl_take isl_set *NewContext) { 1618 NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context)); 1619 isl_set_free(Context); 1620 Context = NewContext; 1621 } 1622 1623 /// @brief Remap parameter values but keep AddRecs valid wrt. invariant loads. 1624 struct SCEVSensitiveParameterRewriter 1625 : public SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *> { 1626 ValueToValueMap &VMap; 1627 ScalarEvolution &SE; 1628 1629 public: 1630 SCEVSensitiveParameterRewriter(ValueToValueMap &VMap, ScalarEvolution &SE) 1631 : VMap(VMap), SE(SE) {} 1632 1633 static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE, 1634 ValueToValueMap &VMap) { 1635 SCEVSensitiveParameterRewriter SSPR(VMap, SE); 1636 return SSPR.visit(E); 1637 } 1638 1639 const SCEV *visit(const SCEV *E) { 1640 return SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *>::visit(E); 1641 } 1642 1643 const SCEV *visitConstant(const SCEVConstant *E) { return E; } 1644 1645 const SCEV *visitTruncateExpr(const SCEVTruncateExpr *E) { 1646 return SE.getTruncateExpr(visit(E->getOperand()), E->getType()); 1647 } 1648 1649 const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *E) { 1650 return SE.getZeroExtendExpr(visit(E->getOperand()), E->getType()); 1651 } 1652 1653 const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *E) { 1654 return SE.getSignExtendExpr(visit(E->getOperand()), E->getType()); 1655 } 1656 1657 const SCEV *visitAddExpr(const SCEVAddExpr *E) { 1658 SmallVector<const SCEV *, 4> Operands; 1659 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1660 Operands.push_back(visit(E->getOperand(i))); 1661 return SE.getAddExpr(Operands); 1662 } 1663 1664 const SCEV *visitMulExpr(const SCEVMulExpr *E) { 1665 SmallVector<const SCEV *, 4> Operands; 1666 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1667 Operands.push_back(visit(E->getOperand(i))); 1668 return SE.getMulExpr(Operands); 1669 } 1670 1671 const SCEV *visitSMaxExpr(const SCEVSMaxExpr *E) { 1672 SmallVector<const SCEV *, 4> Operands; 1673 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1674 Operands.push_back(visit(E->getOperand(i))); 1675 return SE.getSMaxExpr(Operands); 1676 } 1677 1678 const SCEV *visitUMaxExpr(const SCEVUMaxExpr *E) { 1679 SmallVector<const SCEV *, 4> Operands; 1680 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1681 Operands.push_back(visit(E->getOperand(i))); 1682 return SE.getUMaxExpr(Operands); 1683 } 1684 1685 const SCEV *visitUDivExpr(const SCEVUDivExpr *E) { 1686 return SE.getUDivExpr(visit(E->getLHS()), visit(E->getRHS())); 1687 } 1688 1689 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) { 1690 auto *Start = visit(E->getStart()); 1691 auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0), 1692 visit(E->getStepRecurrence(SE)), 1693 E->getLoop(), SCEV::FlagAnyWrap); 1694 return SE.getAddExpr(Start, AddRec); 1695 } 1696 1697 const SCEV *visitUnknown(const SCEVUnknown *E) { 1698 if (auto *NewValue = VMap.lookup(E->getValue())) 1699 return SE.getUnknown(NewValue); 1700 return E; 1701 } 1702 }; 1703 1704 const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *S) { 1705 return SCEVSensitiveParameterRewriter::rewrite(S, *SE, InvEquivClassVMap); 1706 } 1707 1708 void Scop::addParams(std::vector<const SCEV *> NewParameters) { 1709 for (const SCEV *Parameter : NewParameters) { 1710 Parameter = extractConstantFactor(Parameter, *SE).second; 1711 1712 // Normalize the SCEV to get the representing element for an invariant load. 1713 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1714 1715 if (ParameterIds.find(Parameter) != ParameterIds.end()) 1716 continue; 1717 1718 int dimension = Parameters.size(); 1719 1720 Parameters.push_back(Parameter); 1721 ParameterIds[Parameter] = dimension; 1722 } 1723 } 1724 1725 __isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) { 1726 // Normalize the SCEV to get the representing element for an invariant load. 1727 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1728 1729 ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter); 1730 1731 if (IdIter == ParameterIds.end()) 1732 return nullptr; 1733 1734 std::string ParameterName; 1735 1736 ParameterName = "p_" + utostr(IdIter->second); 1737 1738 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) { 1739 Value *Val = ValueParameter->getValue(); 1740 1741 // If this parameter references a specific Value and this value has a name 1742 // we use this name as it is likely to be unique and more useful than just 1743 // a number. 1744 if (Val->hasName()) 1745 ParameterName = Val->getName(); 1746 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) { 1747 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets(); 1748 if (LoadOrigin->hasName()) { 1749 ParameterName += "_loaded_from_"; 1750 ParameterName += 1751 LI->getPointerOperand()->stripInBoundsOffsets()->getName(); 1752 } 1753 } 1754 } 1755 1756 return isl_id_alloc(getIslCtx(), ParameterName.c_str(), 1757 const_cast<void *>((const void *)Parameter)); 1758 } 1759 1760 isl_set *Scop::addNonEmptyDomainConstraints(isl_set *C) const { 1761 isl_set *DomainContext = isl_union_set_params(getDomains()); 1762 return isl_set_intersect_params(C, DomainContext); 1763 } 1764 1765 void Scop::buildBoundaryContext() { 1766 if (IgnoreIntegerWrapping) { 1767 BoundaryContext = isl_set_universe(getParamSpace()); 1768 return; 1769 } 1770 1771 BoundaryContext = Affinator.getWrappingContext(); 1772 1773 // The isl_set_complement operation used to create the boundary context 1774 // can possibly become very expensive. We bound the compile time of 1775 // this operation by setting a compute out. 1776 // 1777 // TODO: We can probably get around using isl_set_complement and directly 1778 // AST generate BoundaryContext. 1779 long MaxOpsOld = isl_ctx_get_max_operations(getIslCtx()); 1780 isl_ctx_reset_operations(getIslCtx()); 1781 isl_ctx_set_max_operations(getIslCtx(), 300000); 1782 isl_options_set_on_error(getIslCtx(), ISL_ON_ERROR_CONTINUE); 1783 1784 BoundaryContext = isl_set_complement(BoundaryContext); 1785 1786 if (isl_ctx_last_error(getIslCtx()) == isl_error_quota) { 1787 isl_set_free(BoundaryContext); 1788 BoundaryContext = isl_set_empty(getParamSpace()); 1789 } 1790 1791 isl_options_set_on_error(getIslCtx(), ISL_ON_ERROR_ABORT); 1792 isl_ctx_reset_operations(getIslCtx()); 1793 isl_ctx_set_max_operations(getIslCtx(), MaxOpsOld); 1794 BoundaryContext = isl_set_gist_params(BoundaryContext, getContext()); 1795 trackAssumption(WRAPPING, BoundaryContext, DebugLoc()); 1796 } 1797 1798 void Scop::addUserAssumptions(AssumptionCache &AC, DominatorTree &DT, 1799 LoopInfo &LI) { 1800 auto *R = &getRegion(); 1801 auto &F = *R->getEntry()->getParent(); 1802 for (auto &Assumption : AC.assumptions()) { 1803 auto *CI = dyn_cast_or_null<CallInst>(Assumption); 1804 if (!CI || CI->getNumArgOperands() != 1) 1805 continue; 1806 if (!DT.dominates(CI->getParent(), R->getEntry())) 1807 continue; 1808 1809 auto *Val = CI->getArgOperand(0); 1810 std::vector<const SCEV *> Params; 1811 if (!isAffineParamConstraint(Val, R, *SE, Params)) { 1812 emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, 1813 CI->getDebugLoc(), 1814 "Non-affine user assumption ignored."); 1815 continue; 1816 } 1817 1818 addParams(Params); 1819 1820 auto *L = LI.getLoopFor(CI->getParent()); 1821 SmallVector<isl_set *, 2> ConditionSets; 1822 buildConditionSets(*this, Val, nullptr, L, Context, ConditionSets); 1823 assert(ConditionSets.size() == 2); 1824 isl_set_free(ConditionSets[1]); 1825 1826 auto *AssumptionCtx = ConditionSets[0]; 1827 emitOptimizationRemarkAnalysis( 1828 F.getContext(), DEBUG_TYPE, F, CI->getDebugLoc(), 1829 "Use user assumption: " + stringFromIslObj(AssumptionCtx)); 1830 Context = isl_set_intersect(Context, AssumptionCtx); 1831 } 1832 } 1833 1834 void Scop::addUserContext() { 1835 if (UserContextStr.empty()) 1836 return; 1837 1838 isl_set *UserContext = 1839 isl_set_read_from_str(getIslCtx(), UserContextStr.c_str()); 1840 isl_space *Space = getParamSpace(); 1841 if (isl_space_dim(Space, isl_dim_param) != 1842 isl_set_dim(UserContext, isl_dim_param)) { 1843 auto SpaceStr = isl_space_to_str(Space); 1844 errs() << "Error: the context provided in -polly-context has not the same " 1845 << "number of dimensions than the computed context. Due to this " 1846 << "mismatch, the -polly-context option is ignored. Please provide " 1847 << "the context in the parameter space: " << SpaceStr << ".\n"; 1848 free(SpaceStr); 1849 isl_set_free(UserContext); 1850 isl_space_free(Space); 1851 return; 1852 } 1853 1854 for (unsigned i = 0; i < isl_space_dim(Space, isl_dim_param); i++) { 1855 auto *NameContext = isl_set_get_dim_name(Context, isl_dim_param, i); 1856 auto *NameUserContext = isl_set_get_dim_name(UserContext, isl_dim_param, i); 1857 1858 if (strcmp(NameContext, NameUserContext) != 0) { 1859 auto SpaceStr = isl_space_to_str(Space); 1860 errs() << "Error: the name of dimension " << i 1861 << " provided in -polly-context " 1862 << "is '" << NameUserContext << "', but the name in the computed " 1863 << "context is '" << NameContext 1864 << "'. Due to this name mismatch, " 1865 << "the -polly-context option is ignored. Please provide " 1866 << "the context in the parameter space: " << SpaceStr << ".\n"; 1867 free(SpaceStr); 1868 isl_set_free(UserContext); 1869 isl_space_free(Space); 1870 return; 1871 } 1872 1873 UserContext = 1874 isl_set_set_dim_id(UserContext, isl_dim_param, i, 1875 isl_space_get_dim_id(Space, isl_dim_param, i)); 1876 } 1877 1878 Context = isl_set_intersect(Context, UserContext); 1879 isl_space_free(Space); 1880 } 1881 1882 void Scop::buildInvariantEquivalenceClasses(ScopDetection &SD) { 1883 DenseMap<std::pair<const SCEV *, Type *>, LoadInst *> EquivClasses; 1884 1885 const InvariantLoadsSetTy &RIL = *SD.getRequiredInvariantLoads(&getRegion()); 1886 for (LoadInst *LInst : RIL) { 1887 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 1888 1889 Type *Ty = LInst->getType(); 1890 LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)]; 1891 if (ClassRep) { 1892 InvEquivClassVMap[LInst] = ClassRep; 1893 continue; 1894 } 1895 1896 ClassRep = LInst; 1897 InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList(), nullptr, 1898 Ty); 1899 } 1900 } 1901 1902 void Scop::buildContext() { 1903 isl_space *Space = isl_space_params_alloc(getIslCtx(), 0); 1904 Context = isl_set_universe(isl_space_copy(Space)); 1905 AssumedContext = isl_set_universe(Space); 1906 } 1907 1908 void Scop::addParameterBounds() { 1909 for (const auto &ParamID : ParameterIds) { 1910 int dim = ParamID.second; 1911 1912 ConstantRange SRange = SE->getSignedRange(ParamID.first); 1913 1914 Context = addRangeBoundsToSet(Context, SRange, dim, isl_dim_param); 1915 } 1916 } 1917 1918 void Scop::realignParams() { 1919 // Add all parameters into a common model. 1920 isl_space *Space = isl_space_params_alloc(getIslCtx(), ParameterIds.size()); 1921 1922 for (const auto &ParamID : ParameterIds) { 1923 const SCEV *Parameter = ParamID.first; 1924 isl_id *id = getIdForParam(Parameter); 1925 Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id); 1926 } 1927 1928 // Align the parameters of all data structures to the model. 1929 Context = isl_set_align_params(Context, Space); 1930 1931 for (ScopStmt &Stmt : *this) 1932 Stmt.realignParams(); 1933 } 1934 1935 static __isl_give isl_set * 1936 simplifyAssumptionContext(__isl_take isl_set *AssumptionContext, 1937 const Scop &S) { 1938 // If we modelt all blocks in the SCoP that have side effects we can simplify 1939 // the context with the constraints that are needed for anything to be 1940 // executed at all. However, if we have error blocks in the SCoP we already 1941 // assumed some parameter combinations cannot occure and removed them from the 1942 // domains, thus we cannot use the remaining domain to simplify the 1943 // assumptions. 1944 if (!S.hasErrorBlock()) { 1945 isl_set *DomainParameters = isl_union_set_params(S.getDomains()); 1946 AssumptionContext = 1947 isl_set_gist_params(AssumptionContext, DomainParameters); 1948 } 1949 1950 AssumptionContext = isl_set_gist_params(AssumptionContext, S.getContext()); 1951 return AssumptionContext; 1952 } 1953 1954 void Scop::simplifyContexts() { 1955 // The parameter constraints of the iteration domains give us a set of 1956 // constraints that need to hold for all cases where at least a single 1957 // statement iteration is executed in the whole scop. We now simplify the 1958 // assumed context under the assumption that such constraints hold and at 1959 // least a single statement iteration is executed. For cases where no 1960 // statement instances are executed, the assumptions we have taken about 1961 // the executed code do not matter and can be changed. 1962 // 1963 // WARNING: This only holds if the assumptions we have taken do not reduce 1964 // the set of statement instances that are executed. Otherwise we 1965 // may run into a case where the iteration domains suggest that 1966 // for a certain set of parameter constraints no code is executed, 1967 // but in the original program some computation would have been 1968 // performed. In such a case, modifying the run-time conditions and 1969 // possibly influencing the run-time check may cause certain scops 1970 // to not be executed. 1971 // 1972 // Example: 1973 // 1974 // When delinearizing the following code: 1975 // 1976 // for (long i = 0; i < 100; i++) 1977 // for (long j = 0; j < m; j++) 1978 // A[i+p][j] = 1.0; 1979 // 1980 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as 1981 // otherwise we would access out of bound data. Now, knowing that code is 1982 // only executed for the case m >= 0, it is sufficient to assume p >= 0. 1983 AssumedContext = simplifyAssumptionContext(AssumedContext, *this); 1984 BoundaryContext = simplifyAssumptionContext(BoundaryContext, *this); 1985 } 1986 1987 /// @brief Add the minimal/maximal access in @p Set to @p User. 1988 static isl_stat buildMinMaxAccess(__isl_take isl_set *Set, void *User) { 1989 Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User; 1990 isl_pw_multi_aff *MinPMA, *MaxPMA; 1991 isl_pw_aff *LastDimAff; 1992 isl_aff *OneAff; 1993 unsigned Pos; 1994 1995 // Restrict the number of parameters involved in the access as the lexmin/ 1996 // lexmax computation will take too long if this number is high. 1997 // 1998 // Experiments with a simple test case using an i7 4800MQ: 1999 // 2000 // #Parameters involved | Time (in sec) 2001 // 6 | 0.01 2002 // 7 | 0.04 2003 // 8 | 0.12 2004 // 9 | 0.40 2005 // 10 | 1.54 2006 // 11 | 6.78 2007 // 12 | 30.38 2008 // 2009 if (isl_set_n_param(Set) > RunTimeChecksMaxParameters) { 2010 unsigned InvolvedParams = 0; 2011 for (unsigned u = 0, e = isl_set_n_param(Set); u < e; u++) 2012 if (isl_set_involves_dims(Set, isl_dim_param, u, 1)) 2013 InvolvedParams++; 2014 2015 if (InvolvedParams > RunTimeChecksMaxParameters) { 2016 isl_set_free(Set); 2017 return isl_stat_error; 2018 } 2019 } 2020 2021 Set = isl_set_remove_divs(Set); 2022 2023 MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set)); 2024 MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set)); 2025 2026 MinPMA = isl_pw_multi_aff_coalesce(MinPMA); 2027 MaxPMA = isl_pw_multi_aff_coalesce(MaxPMA); 2028 2029 // Adjust the last dimension of the maximal access by one as we want to 2030 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer 2031 // we test during code generation might now point after the end of the 2032 // allocated array but we will never dereference it anyway. 2033 assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) && 2034 "Assumed at least one output dimension"); 2035 Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1; 2036 LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos); 2037 OneAff = isl_aff_zero_on_domain( 2038 isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff))); 2039 OneAff = isl_aff_add_constant_si(OneAff, 1); 2040 LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff)); 2041 MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff); 2042 2043 MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA)); 2044 2045 isl_set_free(Set); 2046 return isl_stat_ok; 2047 } 2048 2049 static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) { 2050 isl_set *Domain = MA->getStatement()->getDomain(); 2051 Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain)); 2052 return isl_set_reset_tuple_id(Domain); 2053 } 2054 2055 /// @brief Wrapper function to calculate minimal/maximal accesses to each array. 2056 static bool calculateMinMaxAccess(__isl_take isl_union_map *Accesses, 2057 __isl_take isl_union_set *Domains, 2058 Scop::MinMaxVectorTy &MinMaxAccesses) { 2059 2060 Accesses = isl_union_map_intersect_domain(Accesses, Domains); 2061 isl_union_set *Locations = isl_union_map_range(Accesses); 2062 Locations = isl_union_set_coalesce(Locations); 2063 Locations = isl_union_set_detect_equalities(Locations); 2064 bool Valid = (0 == isl_union_set_foreach_set(Locations, buildMinMaxAccess, 2065 &MinMaxAccesses)); 2066 isl_union_set_free(Locations); 2067 return Valid; 2068 } 2069 2070 /// @brief Helper to treat non-affine regions and basic blocks the same. 2071 /// 2072 ///{ 2073 2074 /// @brief Return the block that is the representing block for @p RN. 2075 static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) { 2076 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry() 2077 : RN->getNodeAs<BasicBlock>(); 2078 } 2079 2080 /// @brief Return the @p idx'th block that is executed after @p RN. 2081 static inline BasicBlock * 2082 getRegionNodeSuccessor(RegionNode *RN, TerminatorInst *TI, unsigned idx) { 2083 if (RN->isSubRegion()) { 2084 assert(idx == 0); 2085 return RN->getNodeAs<Region>()->getExit(); 2086 } 2087 return TI->getSuccessor(idx); 2088 } 2089 2090 /// @brief Return the smallest loop surrounding @p RN. 2091 static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) { 2092 if (!RN->isSubRegion()) 2093 return LI.getLoopFor(RN->getNodeAs<BasicBlock>()); 2094 2095 Region *NonAffineSubRegion = RN->getNodeAs<Region>(); 2096 Loop *L = LI.getLoopFor(NonAffineSubRegion->getEntry()); 2097 while (L && NonAffineSubRegion->contains(L)) 2098 L = L->getParentLoop(); 2099 return L; 2100 } 2101 2102 static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) { 2103 if (!RN->isSubRegion()) 2104 return 1; 2105 2106 Region *R = RN->getNodeAs<Region>(); 2107 return std::distance(R->block_begin(), R->block_end()); 2108 } 2109 2110 static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI, 2111 const DominatorTree &DT) { 2112 if (!RN->isSubRegion()) 2113 return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT); 2114 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks()) 2115 if (isErrorBlock(*BB, R, LI, DT)) 2116 return true; 2117 return false; 2118 } 2119 2120 ///} 2121 2122 static inline __isl_give isl_set *addDomainDimId(__isl_take isl_set *Domain, 2123 unsigned Dim, Loop *L) { 2124 Domain = isl_set_lower_bound_si(Domain, isl_dim_set, Dim, -1); 2125 isl_id *DimId = 2126 isl_id_alloc(isl_set_get_ctx(Domain), nullptr, static_cast<void *>(L)); 2127 return isl_set_set_dim_id(Domain, isl_dim_set, Dim, DimId); 2128 } 2129 2130 isl_set *Scop::getDomainConditions(ScopStmt *Stmt) { 2131 return getDomainConditions(Stmt->getEntryBlock()); 2132 } 2133 2134 isl_set *Scop::getDomainConditions(BasicBlock *BB) { 2135 assert(DomainMap.count(BB) && "Requested BB did not have a domain"); 2136 return isl_set_copy(DomainMap[BB]); 2137 } 2138 2139 void Scop::removeErrorBlockDomains(ScopDetection &SD, DominatorTree &DT, 2140 LoopInfo &LI) { 2141 auto removeDomains = [this, &DT](BasicBlock *Start) { 2142 auto *BBNode = DT.getNode(Start); 2143 for (auto *ErrorChild : depth_first(BBNode)) { 2144 auto *ErrorChildBlock = ErrorChild->getBlock(); 2145 auto *CurrentDomain = DomainMap[ErrorChildBlock]; 2146 auto *Empty = isl_set_empty(isl_set_get_space(CurrentDomain)); 2147 DomainMap[ErrorChildBlock] = Empty; 2148 isl_set_free(CurrentDomain); 2149 } 2150 }; 2151 2152 SmallVector<Region *, 4> Todo = {&R}; 2153 2154 while (!Todo.empty()) { 2155 auto *SubRegion = Todo.back(); 2156 Todo.pop_back(); 2157 2158 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) { 2159 for (auto &Child : *SubRegion) 2160 Todo.push_back(Child.get()); 2161 continue; 2162 } 2163 if (containsErrorBlock(SubRegion->getNode(), getRegion(), LI, DT)) 2164 removeDomains(SubRegion->getEntry()); 2165 } 2166 2167 for (auto *BB : R.blocks()) 2168 if (isErrorBlock(*BB, R, LI, DT)) 2169 removeDomains(BB); 2170 } 2171 2172 void Scop::buildDomains(Region *R, ScopDetection &SD, DominatorTree &DT, 2173 LoopInfo &LI) { 2174 2175 bool IsOnlyNonAffineRegion = SD.isNonAffineSubRegion(R, R); 2176 auto *EntryBB = R->getEntry(); 2177 auto *L = IsOnlyNonAffineRegion ? nullptr : LI.getLoopFor(EntryBB); 2178 int LD = getRelativeLoopDepth(L); 2179 auto *S = isl_set_universe(isl_space_set_alloc(getIslCtx(), 0, LD + 1)); 2180 2181 while (LD-- >= 0) { 2182 S = addDomainDimId(S, LD + 1, L); 2183 L = L->getParentLoop(); 2184 } 2185 2186 DomainMap[EntryBB] = S; 2187 2188 if (IsOnlyNonAffineRegion) 2189 return; 2190 2191 buildDomainsWithBranchConstraints(R, SD, DT, LI); 2192 propagateDomainConstraints(R, SD, DT, LI); 2193 2194 // Error blocks and blocks dominated by them have been assumed to never be 2195 // executed. Representing them in the Scop does not add any value. In fact, 2196 // it is likely to cause issues during construction of the ScopStmts. The 2197 // contents of error blocks have not been verfied to be expressible and 2198 // will cause problems when building up a ScopStmt for them. 2199 // Furthermore, basic blocks dominated by error blocks may reference 2200 // instructions in the error block which, if the error block is not modeled, 2201 // can themselves not be constructed properly. 2202 removeErrorBlockDomains(SD, DT, LI); 2203 } 2204 2205 void Scop::buildDomainsWithBranchConstraints(Region *R, ScopDetection &SD, 2206 DominatorTree &DT, LoopInfo &LI) { 2207 auto &BoxedLoops = *SD.getBoxedLoops(&getRegion()); 2208 2209 // To create the domain for each block in R we iterate over all blocks and 2210 // subregions in R and propagate the conditions under which the current region 2211 // element is executed. To this end we iterate in reverse post order over R as 2212 // it ensures that we first visit all predecessors of a region node (either a 2213 // basic block or a subregion) before we visit the region node itself. 2214 // Initially, only the domain for the SCoP region entry block is set and from 2215 // there we propagate the current domain to all successors, however we add the 2216 // condition that the successor is actually executed next. 2217 // As we are only interested in non-loop carried constraints here we can 2218 // simply skip loop back edges. 2219 2220 ReversePostOrderTraversal<Region *> RTraversal(R); 2221 for (auto *RN : RTraversal) { 2222 2223 // Recurse for affine subregions but go on for basic blocks and non-affine 2224 // subregions. 2225 if (RN->isSubRegion()) { 2226 Region *SubRegion = RN->getNodeAs<Region>(); 2227 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) { 2228 buildDomainsWithBranchConstraints(SubRegion, SD, DT, LI); 2229 continue; 2230 } 2231 } 2232 2233 if (containsErrorBlock(RN, getRegion(), LI, DT)) 2234 HasErrorBlock = true; 2235 2236 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2237 TerminatorInst *TI = BB->getTerminator(); 2238 2239 if (isa<UnreachableInst>(TI)) 2240 continue; 2241 2242 isl_set *Domain = DomainMap.lookup(BB); 2243 if (!Domain) 2244 continue; 2245 2246 Loop *BBLoop = getRegionNodeLoop(RN, LI); 2247 int BBLoopDepth = getRelativeLoopDepth(BBLoop); 2248 2249 // Build the condition sets for the successor nodes of the current region 2250 // node. If it is a non-affine subregion we will always execute the single 2251 // exit node, hence the single entry node domain is the condition set. For 2252 // basic blocks we use the helper function buildConditionSets. 2253 SmallVector<isl_set *, 8> ConditionSets; 2254 if (RN->isSubRegion()) 2255 ConditionSets.push_back(isl_set_copy(Domain)); 2256 else 2257 buildConditionSets(*this, TI, BBLoop, Domain, ConditionSets); 2258 2259 // Now iterate over the successors and set their initial domain based on 2260 // their condition set. We skip back edges here and have to be careful when 2261 // we leave a loop not to keep constraints over a dimension that doesn't 2262 // exist anymore. 2263 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size()); 2264 for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) { 2265 isl_set *CondSet = ConditionSets[u]; 2266 BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u); 2267 2268 // Skip back edges. 2269 if (DT.dominates(SuccBB, BB)) { 2270 isl_set_free(CondSet); 2271 continue; 2272 } 2273 2274 // Do not adjust the number of dimensions if we enter a boxed loop or are 2275 // in a non-affine subregion or if the surrounding loop stays the same. 2276 Loop *SuccBBLoop = LI.getLoopFor(SuccBB); 2277 while (BoxedLoops.count(SuccBBLoop)) 2278 SuccBBLoop = SuccBBLoop->getParentLoop(); 2279 2280 if (BBLoop != SuccBBLoop) { 2281 2282 // Check if the edge to SuccBB is a loop entry or exit edge. If so 2283 // adjust the dimensionality accordingly. Lastly, if we leave a loop 2284 // and enter a new one we need to drop the old constraints. 2285 int SuccBBLoopDepth = getRelativeLoopDepth(SuccBBLoop); 2286 unsigned LoopDepthDiff = std::abs(BBLoopDepth - SuccBBLoopDepth); 2287 if (BBLoopDepth > SuccBBLoopDepth) { 2288 CondSet = isl_set_project_out(CondSet, isl_dim_set, 2289 isl_set_n_dim(CondSet) - LoopDepthDiff, 2290 LoopDepthDiff); 2291 } else if (SuccBBLoopDepth > BBLoopDepth) { 2292 assert(LoopDepthDiff == 1); 2293 CondSet = isl_set_add_dims(CondSet, isl_dim_set, 1); 2294 CondSet = addDomainDimId(CondSet, SuccBBLoopDepth, SuccBBLoop); 2295 } else if (BBLoopDepth >= 0) { 2296 assert(LoopDepthDiff <= 1); 2297 CondSet = isl_set_project_out(CondSet, isl_dim_set, BBLoopDepth, 1); 2298 CondSet = isl_set_add_dims(CondSet, isl_dim_set, 1); 2299 CondSet = addDomainDimId(CondSet, SuccBBLoopDepth, SuccBBLoop); 2300 } 2301 } 2302 2303 // Set the domain for the successor or merge it with an existing domain in 2304 // case there are multiple paths (without loop back edges) to the 2305 // successor block. 2306 isl_set *&SuccDomain = DomainMap[SuccBB]; 2307 if (!SuccDomain) 2308 SuccDomain = CondSet; 2309 else 2310 SuccDomain = isl_set_union(SuccDomain, CondSet); 2311 2312 SuccDomain = isl_set_coalesce(SuccDomain); 2313 if (isl_set_n_basic_set(SuccDomain) > MaxConjunctsInDomain) { 2314 auto *Empty = isl_set_empty(isl_set_get_space(SuccDomain)); 2315 isl_set_free(SuccDomain); 2316 SuccDomain = Empty; 2317 invalidate(ERROR_DOMAINCONJUNCTS, DebugLoc()); 2318 } 2319 } 2320 } 2321 } 2322 2323 /// @brief Return the domain for @p BB wrt @p DomainMap. 2324 /// 2325 /// This helper function will lookup @p BB in @p DomainMap but also handle the 2326 /// case where @p BB is contained in a non-affine subregion using the region 2327 /// tree obtained by @p RI. 2328 static __isl_give isl_set * 2329 getDomainForBlock(BasicBlock *BB, DenseMap<BasicBlock *, isl_set *> &DomainMap, 2330 RegionInfo &RI) { 2331 auto DIt = DomainMap.find(BB); 2332 if (DIt != DomainMap.end()) 2333 return isl_set_copy(DIt->getSecond()); 2334 2335 Region *R = RI.getRegionFor(BB); 2336 while (R->getEntry() == BB) 2337 R = R->getParent(); 2338 return getDomainForBlock(R->getEntry(), DomainMap, RI); 2339 } 2340 2341 void Scop::propagateDomainConstraints(Region *R, ScopDetection &SD, 2342 DominatorTree &DT, LoopInfo &LI) { 2343 // Iterate over the region R and propagate the domain constrains from the 2344 // predecessors to the current node. In contrast to the 2345 // buildDomainsWithBranchConstraints function, this one will pull the domain 2346 // information from the predecessors instead of pushing it to the successors. 2347 // Additionally, we assume the domains to be already present in the domain 2348 // map here. However, we iterate again in reverse post order so we know all 2349 // predecessors have been visited before a block or non-affine subregion is 2350 // visited. 2351 2352 // The set of boxed loops (loops in non-affine subregions) for this SCoP. 2353 auto &BoxedLoops = *SD.getBoxedLoops(&getRegion()); 2354 2355 ReversePostOrderTraversal<Region *> RTraversal(R); 2356 for (auto *RN : RTraversal) { 2357 2358 // Recurse for affine subregions but go on for basic blocks and non-affine 2359 // subregions. 2360 if (RN->isSubRegion()) { 2361 Region *SubRegion = RN->getNodeAs<Region>(); 2362 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) { 2363 propagateDomainConstraints(SubRegion, SD, DT, LI); 2364 continue; 2365 } 2366 } 2367 2368 // Get the domain for the current block and check if it was initialized or 2369 // not. The only way it was not is if this block is only reachable via error 2370 // blocks, thus will not be executed under the assumptions we make. Such 2371 // blocks have to be skipped as their predecessors might not have domains 2372 // either. It would not benefit us to compute the domain anyway, only the 2373 // domains of the error blocks that are reachable from non-error blocks 2374 // are needed to generate assumptions. 2375 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2376 isl_set *&Domain = DomainMap[BB]; 2377 if (!Domain) { 2378 DomainMap.erase(BB); 2379 continue; 2380 } 2381 2382 Loop *BBLoop = getRegionNodeLoop(RN, LI); 2383 int BBLoopDepth = getRelativeLoopDepth(BBLoop); 2384 2385 isl_set *PredDom = isl_set_empty(isl_set_get_space(Domain)); 2386 for (auto *PredBB : predecessors(BB)) { 2387 2388 // Skip backedges 2389 if (DT.dominates(BB, PredBB)) 2390 continue; 2391 2392 isl_set *PredBBDom = nullptr; 2393 2394 // Handle the SCoP entry block with its outside predecessors. 2395 if (!getRegion().contains(PredBB)) 2396 PredBBDom = isl_set_universe(isl_set_get_space(PredDom)); 2397 2398 if (!PredBBDom) { 2399 // Determine the loop depth of the predecessor and adjust its domain to 2400 // the domain of the current block. This can mean we have to: 2401 // o) Drop a dimension if this block is the exit of a loop, not the 2402 // header of a new loop and the predecessor was part of the loop. 2403 // o) Add an unconstrainted new dimension if this block is the header 2404 // of a loop and the predecessor is not part of it. 2405 // o) Drop the information about the innermost loop dimension when the 2406 // predecessor and the current block are surrounded by different 2407 // loops in the same depth. 2408 PredBBDom = getDomainForBlock(PredBB, DomainMap, *R->getRegionInfo()); 2409 Loop *PredBBLoop = LI.getLoopFor(PredBB); 2410 while (BoxedLoops.count(PredBBLoop)) 2411 PredBBLoop = PredBBLoop->getParentLoop(); 2412 2413 int PredBBLoopDepth = getRelativeLoopDepth(PredBBLoop); 2414 unsigned LoopDepthDiff = std::abs(BBLoopDepth - PredBBLoopDepth); 2415 if (BBLoopDepth < PredBBLoopDepth) 2416 PredBBDom = isl_set_project_out( 2417 PredBBDom, isl_dim_set, isl_set_n_dim(PredBBDom) - LoopDepthDiff, 2418 LoopDepthDiff); 2419 else if (PredBBLoopDepth < BBLoopDepth) { 2420 assert(LoopDepthDiff == 1); 2421 PredBBDom = isl_set_add_dims(PredBBDom, isl_dim_set, 1); 2422 } else if (BBLoop != PredBBLoop && BBLoopDepth >= 0) { 2423 assert(LoopDepthDiff <= 1); 2424 PredBBDom = isl_set_drop_constraints_involving_dims( 2425 PredBBDom, isl_dim_set, BBLoopDepth, 1); 2426 } 2427 } 2428 2429 PredDom = isl_set_union(PredDom, PredBBDom); 2430 } 2431 2432 // Under the union of all predecessor conditions we can reach this block. 2433 Domain = isl_set_coalesce(isl_set_intersect(Domain, PredDom)); 2434 2435 if (BBLoop && BBLoop->getHeader() == BB && getRegion().contains(BBLoop)) 2436 addLoopBoundsToHeaderDomain(BBLoop, LI); 2437 2438 // Add assumptions for error blocks. 2439 if (containsErrorBlock(RN, getRegion(), LI, DT)) { 2440 IsOptimized = true; 2441 isl_set *DomPar = isl_set_params(isl_set_copy(Domain)); 2442 addAssumption(ERRORBLOCK, isl_set_complement(DomPar), 2443 BB->getTerminator()->getDebugLoc()); 2444 } 2445 } 2446 } 2447 2448 /// @brief Create a map from SetSpace -> SetSpace where the dimensions @p Dim 2449 /// is incremented by one and all other dimensions are equal, e.g., 2450 /// [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3] 2451 /// if @p Dim is 2 and @p SetSpace has 4 dimensions. 2452 static __isl_give isl_map * 2453 createNextIterationMap(__isl_take isl_space *SetSpace, unsigned Dim) { 2454 auto *MapSpace = isl_space_map_from_set(SetSpace); 2455 auto *NextIterationMap = isl_map_universe(isl_space_copy(MapSpace)); 2456 for (unsigned u = 0; u < isl_map_n_in(NextIterationMap); u++) 2457 if (u != Dim) 2458 NextIterationMap = 2459 isl_map_equate(NextIterationMap, isl_dim_in, u, isl_dim_out, u); 2460 auto *C = isl_constraint_alloc_equality(isl_local_space_from_space(MapSpace)); 2461 C = isl_constraint_set_constant_si(C, 1); 2462 C = isl_constraint_set_coefficient_si(C, isl_dim_in, Dim, 1); 2463 C = isl_constraint_set_coefficient_si(C, isl_dim_out, Dim, -1); 2464 NextIterationMap = isl_map_add_constraint(NextIterationMap, C); 2465 return NextIterationMap; 2466 } 2467 2468 void Scop::addLoopBoundsToHeaderDomain(Loop *L, LoopInfo &LI) { 2469 int LoopDepth = getRelativeLoopDepth(L); 2470 assert(LoopDepth >= 0 && "Loop in region should have at least depth one"); 2471 2472 BasicBlock *HeaderBB = L->getHeader(); 2473 assert(DomainMap.count(HeaderBB)); 2474 isl_set *&HeaderBBDom = DomainMap[HeaderBB]; 2475 2476 isl_map *NextIterationMap = 2477 createNextIterationMap(isl_set_get_space(HeaderBBDom), LoopDepth); 2478 2479 isl_set *UnionBackedgeCondition = 2480 isl_set_empty(isl_set_get_space(HeaderBBDom)); 2481 2482 SmallVector<llvm::BasicBlock *, 4> LatchBlocks; 2483 L->getLoopLatches(LatchBlocks); 2484 2485 for (BasicBlock *LatchBB : LatchBlocks) { 2486 2487 // If the latch is only reachable via error statements we skip it. 2488 isl_set *LatchBBDom = DomainMap.lookup(LatchBB); 2489 if (!LatchBBDom) 2490 continue; 2491 2492 isl_set *BackedgeCondition = nullptr; 2493 2494 TerminatorInst *TI = LatchBB->getTerminator(); 2495 BranchInst *BI = dyn_cast<BranchInst>(TI); 2496 if (BI && BI->isUnconditional()) 2497 BackedgeCondition = isl_set_copy(LatchBBDom); 2498 else { 2499 SmallVector<isl_set *, 8> ConditionSets; 2500 int idx = BI->getSuccessor(0) != HeaderBB; 2501 buildConditionSets(*this, TI, L, LatchBBDom, ConditionSets); 2502 2503 // Free the non back edge condition set as we do not need it. 2504 isl_set_free(ConditionSets[1 - idx]); 2505 2506 BackedgeCondition = ConditionSets[idx]; 2507 } 2508 2509 int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB)); 2510 assert(LatchLoopDepth >= LoopDepth); 2511 BackedgeCondition = 2512 isl_set_project_out(BackedgeCondition, isl_dim_set, LoopDepth + 1, 2513 LatchLoopDepth - LoopDepth); 2514 UnionBackedgeCondition = 2515 isl_set_union(UnionBackedgeCondition, BackedgeCondition); 2516 } 2517 2518 isl_map *ForwardMap = isl_map_lex_le(isl_set_get_space(HeaderBBDom)); 2519 for (int i = 0; i < LoopDepth; i++) 2520 ForwardMap = isl_map_equate(ForwardMap, isl_dim_in, i, isl_dim_out, i); 2521 2522 isl_set *UnionBackedgeConditionComplement = 2523 isl_set_complement(UnionBackedgeCondition); 2524 UnionBackedgeConditionComplement = isl_set_lower_bound_si( 2525 UnionBackedgeConditionComplement, isl_dim_set, LoopDepth, 0); 2526 UnionBackedgeConditionComplement = 2527 isl_set_apply(UnionBackedgeConditionComplement, ForwardMap); 2528 HeaderBBDom = isl_set_subtract(HeaderBBDom, UnionBackedgeConditionComplement); 2529 HeaderBBDom = isl_set_apply(HeaderBBDom, NextIterationMap); 2530 2531 auto Parts = partitionSetParts(HeaderBBDom, LoopDepth); 2532 HeaderBBDom = Parts.second; 2533 2534 // Check if there is a <nsw> tagged AddRec for this loop and if so do not add 2535 // the bounded assumptions to the context as they are already implied by the 2536 // <nsw> tag. 2537 if (Affinator.hasNSWAddRecForLoop(L)) { 2538 isl_set_free(Parts.first); 2539 return; 2540 } 2541 2542 isl_set *UnboundedCtx = isl_set_params(Parts.first); 2543 isl_set *BoundedCtx = isl_set_complement(UnboundedCtx); 2544 addAssumption(INFINITELOOP, BoundedCtx, 2545 HeaderBB->getTerminator()->getDebugLoc()); 2546 } 2547 2548 void Scop::buildAliasChecks(AliasAnalysis &AA) { 2549 if (!PollyUseRuntimeAliasChecks) 2550 return; 2551 2552 if (buildAliasGroups(AA)) 2553 return; 2554 2555 // If a problem occurs while building the alias groups we need to delete 2556 // this SCoP and pretend it wasn't valid in the first place. To this end 2557 // we make the assumed context infeasible. 2558 invalidate(ALIASING, DebugLoc()); 2559 2560 DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << getNameStr() 2561 << " could not be created as the number of parameters involved " 2562 "is too high. The SCoP will be " 2563 "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust " 2564 "the maximal number of parameters but be advised that the " 2565 "compile time might increase exponentially.\n\n"); 2566 } 2567 2568 bool Scop::buildAliasGroups(AliasAnalysis &AA) { 2569 // To create sound alias checks we perform the following steps: 2570 // o) Use the alias analysis and an alias set tracker to build alias sets 2571 // for all memory accesses inside the SCoP. 2572 // o) For each alias set we then map the aliasing pointers back to the 2573 // memory accesses we know, thus obtain groups of memory accesses which 2574 // might alias. 2575 // o) We divide each group based on the domains of the minimal/maximal 2576 // accesses. That means two minimal/maximal accesses are only in a group 2577 // if their access domains intersect, otherwise they are in different 2578 // ones. 2579 // o) We partition each group into read only and non read only accesses. 2580 // o) For each group with more than one base pointer we then compute minimal 2581 // and maximal accesses to each array of a group in read only and non 2582 // read only partitions separately. 2583 using AliasGroupTy = SmallVector<MemoryAccess *, 4>; 2584 2585 AliasSetTracker AST(AA); 2586 2587 DenseMap<Value *, MemoryAccess *> PtrToAcc; 2588 DenseSet<Value *> HasWriteAccess; 2589 for (ScopStmt &Stmt : *this) { 2590 2591 // Skip statements with an empty domain as they will never be executed. 2592 isl_set *StmtDomain = Stmt.getDomain(); 2593 bool StmtDomainEmpty = isl_set_is_empty(StmtDomain); 2594 isl_set_free(StmtDomain); 2595 if (StmtDomainEmpty) 2596 continue; 2597 2598 for (MemoryAccess *MA : Stmt) { 2599 if (MA->isScalarKind()) 2600 continue; 2601 if (!MA->isRead()) 2602 HasWriteAccess.insert(MA->getBaseAddr()); 2603 MemAccInst Acc(MA->getAccessInstruction()); 2604 if (MA->isRead() && isa<MemTransferInst>(Acc)) 2605 PtrToAcc[cast<MemTransferInst>(Acc)->getSource()] = MA; 2606 else 2607 PtrToAcc[Acc.getPointerOperand()] = MA; 2608 AST.add(Acc); 2609 } 2610 } 2611 2612 SmallVector<AliasGroupTy, 4> AliasGroups; 2613 for (AliasSet &AS : AST) { 2614 if (AS.isMustAlias() || AS.isForwardingAliasSet()) 2615 continue; 2616 AliasGroupTy AG; 2617 for (auto &PR : AS) 2618 AG.push_back(PtrToAcc[PR.getValue()]); 2619 if (AG.size() < 2) 2620 continue; 2621 AliasGroups.push_back(std::move(AG)); 2622 } 2623 2624 // Split the alias groups based on their domain. 2625 for (unsigned u = 0; u < AliasGroups.size(); u++) { 2626 AliasGroupTy NewAG; 2627 AliasGroupTy &AG = AliasGroups[u]; 2628 AliasGroupTy::iterator AGI = AG.begin(); 2629 isl_set *AGDomain = getAccessDomain(*AGI); 2630 while (AGI != AG.end()) { 2631 MemoryAccess *MA = *AGI; 2632 isl_set *MADomain = getAccessDomain(MA); 2633 if (isl_set_is_disjoint(AGDomain, MADomain)) { 2634 NewAG.push_back(MA); 2635 AGI = AG.erase(AGI); 2636 isl_set_free(MADomain); 2637 } else { 2638 AGDomain = isl_set_union(AGDomain, MADomain); 2639 AGI++; 2640 } 2641 } 2642 if (NewAG.size() > 1) 2643 AliasGroups.push_back(std::move(NewAG)); 2644 isl_set_free(AGDomain); 2645 } 2646 2647 auto &F = *getRegion().getEntry()->getParent(); 2648 MapVector<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs; 2649 SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues; 2650 for (AliasGroupTy &AG : AliasGroups) { 2651 NonReadOnlyBaseValues.clear(); 2652 ReadOnlyPairs.clear(); 2653 2654 if (AG.size() < 2) { 2655 AG.clear(); 2656 continue; 2657 } 2658 2659 for (auto II = AG.begin(); II != AG.end();) { 2660 emitOptimizationRemarkAnalysis( 2661 F.getContext(), DEBUG_TYPE, F, 2662 (*II)->getAccessInstruction()->getDebugLoc(), 2663 "Possibly aliasing pointer, use restrict keyword."); 2664 2665 Value *BaseAddr = (*II)->getBaseAddr(); 2666 if (HasWriteAccess.count(BaseAddr)) { 2667 NonReadOnlyBaseValues.insert(BaseAddr); 2668 II++; 2669 } else { 2670 ReadOnlyPairs[BaseAddr].insert(*II); 2671 II = AG.erase(II); 2672 } 2673 } 2674 2675 // If we don't have read only pointers check if there are at least two 2676 // non read only pointers, otherwise clear the alias group. 2677 if (ReadOnlyPairs.empty() && NonReadOnlyBaseValues.size() <= 1) { 2678 AG.clear(); 2679 continue; 2680 } 2681 2682 // If we don't have non read only pointers clear the alias group. 2683 if (NonReadOnlyBaseValues.empty()) { 2684 AG.clear(); 2685 continue; 2686 } 2687 2688 // Check if we have non-affine accesses left, if so bail out as we cannot 2689 // generate a good access range yet. 2690 for (auto *MA : AG) 2691 if (!MA->isAffine()) { 2692 invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc()); 2693 return false; 2694 } 2695 for (auto &ReadOnlyPair : ReadOnlyPairs) 2696 for (auto *MA : ReadOnlyPair.second) 2697 if (!MA->isAffine()) { 2698 invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc()); 2699 return false; 2700 } 2701 2702 // Calculate minimal and maximal accesses for non read only accesses. 2703 MinMaxAliasGroups.emplace_back(); 2704 MinMaxVectorPairTy &pair = MinMaxAliasGroups.back(); 2705 MinMaxVectorTy &MinMaxAccessesNonReadOnly = pair.first; 2706 MinMaxVectorTy &MinMaxAccessesReadOnly = pair.second; 2707 MinMaxAccessesNonReadOnly.reserve(AG.size()); 2708 2709 isl_union_map *Accesses = isl_union_map_empty(getParamSpace()); 2710 2711 // AG contains only non read only accesses. 2712 for (MemoryAccess *MA : AG) 2713 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation()); 2714 2715 bool Valid = calculateMinMaxAccess(Accesses, getDomains(), 2716 MinMaxAccessesNonReadOnly); 2717 2718 // Bail out if the number of values we need to compare is too large. 2719 // This is important as the number of comparisions grows quadratically with 2720 // the number of values we need to compare. 2721 if (!Valid || (MinMaxAccessesNonReadOnly.size() + !ReadOnlyPairs.empty() > 2722 RunTimeChecksMaxArraysPerGroup)) 2723 return false; 2724 2725 // Calculate minimal and maximal accesses for read only accesses. 2726 MinMaxAccessesReadOnly.reserve(ReadOnlyPairs.size()); 2727 Accesses = isl_union_map_empty(getParamSpace()); 2728 2729 for (const auto &ReadOnlyPair : ReadOnlyPairs) 2730 for (MemoryAccess *MA : ReadOnlyPair.second) 2731 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation()); 2732 2733 Valid = 2734 calculateMinMaxAccess(Accesses, getDomains(), MinMaxAccessesReadOnly); 2735 2736 if (!Valid) 2737 return false; 2738 } 2739 2740 return true; 2741 } 2742 2743 /// @brief Get the smallest loop that contains @p R but is not in @p R. 2744 static Loop *getLoopSurroundingRegion(Region &R, LoopInfo &LI) { 2745 // Start with the smallest loop containing the entry and expand that 2746 // loop until it contains all blocks in the region. If there is a loop 2747 // containing all blocks in the region check if it is itself contained 2748 // and if so take the parent loop as it will be the smallest containing 2749 // the region but not contained by it. 2750 Loop *L = LI.getLoopFor(R.getEntry()); 2751 while (L) { 2752 bool AllContained = true; 2753 for (auto *BB : R.blocks()) 2754 AllContained &= L->contains(BB); 2755 if (AllContained) 2756 break; 2757 L = L->getParentLoop(); 2758 } 2759 2760 return L ? (R.contains(L) ? L->getParentLoop() : L) : nullptr; 2761 } 2762 2763 static unsigned getMaxLoopDepthInRegion(const Region &R, LoopInfo &LI, 2764 ScopDetection &SD) { 2765 2766 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD.getBoxedLoops(&R); 2767 2768 unsigned MinLD = INT_MAX, MaxLD = 0; 2769 for (BasicBlock *BB : R.blocks()) { 2770 if (Loop *L = LI.getLoopFor(BB)) { 2771 if (!R.contains(L)) 2772 continue; 2773 if (BoxedLoops && BoxedLoops->count(L)) 2774 continue; 2775 unsigned LD = L->getLoopDepth(); 2776 MinLD = std::min(MinLD, LD); 2777 MaxLD = std::max(MaxLD, LD); 2778 } 2779 } 2780 2781 // Handle the case that there is no loop in the SCoP first. 2782 if (MaxLD == 0) 2783 return 1; 2784 2785 assert(MinLD >= 1 && "Minimal loop depth should be at least one"); 2786 assert(MaxLD >= MinLD && 2787 "Maximal loop depth was smaller than mininaml loop depth?"); 2788 return MaxLD - MinLD + 1; 2789 } 2790 2791 Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, unsigned MaxLoopDepth) 2792 : SE(&ScalarEvolution), R(R), IsOptimized(false), 2793 HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false), 2794 MaxLoopDepth(MaxLoopDepth), IslCtx(isl_ctx_alloc(), isl_ctx_free), 2795 Context(nullptr), Affinator(this), AssumedContext(nullptr), 2796 BoundaryContext(nullptr), Schedule(nullptr) { 2797 isl_options_set_on_error(getIslCtx(), ISL_ON_ERROR_ABORT); 2798 buildContext(); 2799 } 2800 2801 void Scop::init(AliasAnalysis &AA, AssumptionCache &AC, ScopDetection &SD, 2802 DominatorTree &DT, LoopInfo &LI) { 2803 addUserAssumptions(AC, DT, LI); 2804 buildInvariantEquivalenceClasses(SD); 2805 2806 buildDomains(&R, SD, DT, LI); 2807 2808 // Remove empty and ignored statements. 2809 // Exit early in case there are no executable statements left in this scop. 2810 simplifySCoP(true, DT, LI); 2811 if (Stmts.empty()) 2812 return; 2813 2814 // The ScopStmts now have enough information to initialize themselves. 2815 for (ScopStmt &Stmt : Stmts) 2816 Stmt.init(SD); 2817 2818 buildSchedule(SD, LI); 2819 2820 if (isl_set_is_empty(AssumedContext)) 2821 return; 2822 2823 updateAccessDimensionality(); 2824 realignParams(); 2825 addParameterBounds(); 2826 addUserContext(); 2827 buildBoundaryContext(); 2828 simplifyContexts(); 2829 buildAliasChecks(AA); 2830 2831 hoistInvariantLoads(SD); 2832 simplifySCoP(false, DT, LI); 2833 } 2834 2835 Scop::~Scop() { 2836 isl_set_free(Context); 2837 isl_set_free(AssumedContext); 2838 isl_set_free(BoundaryContext); 2839 isl_schedule_free(Schedule); 2840 2841 for (auto It : DomainMap) 2842 isl_set_free(It.second); 2843 2844 // Free the alias groups 2845 for (MinMaxVectorPairTy &MinMaxAccessPair : MinMaxAliasGroups) { 2846 for (MinMaxAccessTy &MMA : MinMaxAccessPair.first) { 2847 isl_pw_multi_aff_free(MMA.first); 2848 isl_pw_multi_aff_free(MMA.second); 2849 } 2850 for (MinMaxAccessTy &MMA : MinMaxAccessPair.second) { 2851 isl_pw_multi_aff_free(MMA.first); 2852 isl_pw_multi_aff_free(MMA.second); 2853 } 2854 } 2855 2856 for (const auto &IAClass : InvariantEquivClasses) 2857 isl_set_free(std::get<2>(IAClass)); 2858 2859 // Explicitly release all Scop objects and the underlying isl objects before 2860 // we relase the isl context. 2861 Stmts.clear(); 2862 ScopArrayInfoMap.clear(); 2863 AccFuncMap.clear(); 2864 } 2865 2866 void Scop::updateAccessDimensionality() { 2867 // Check all array accesses for each base pointer and find a (virtual) element 2868 // size for the base pointer that divides all access functions. 2869 for (auto &Stmt : *this) 2870 for (auto *Access : Stmt) { 2871 if (!Access->isArrayKind()) 2872 continue; 2873 auto &SAI = ScopArrayInfoMap[std::make_pair(Access->getBaseAddr(), 2874 ScopArrayInfo::MK_Array)]; 2875 if (SAI->getNumberOfDimensions() != 1) 2876 continue; 2877 unsigned DivisibleSize = SAI->getElemSizeInBytes(); 2878 auto *Subscript = Access->getSubscript(0); 2879 while (!isDivisible(Subscript, DivisibleSize, *SE)) 2880 DivisibleSize /= 2; 2881 auto *Ty = IntegerType::get(SE->getContext(), DivisibleSize * 8); 2882 SAI->updateElementType(Ty); 2883 } 2884 2885 for (auto &Stmt : *this) 2886 for (auto &Access : Stmt) 2887 Access->updateDimensionality(); 2888 } 2889 2890 void Scop::simplifySCoP(bool RemoveIgnoredStmts, DominatorTree &DT, 2891 LoopInfo &LI) { 2892 for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) { 2893 ScopStmt &Stmt = *StmtIt; 2894 RegionNode *RN = Stmt.getRegionNode(); 2895 2896 bool RemoveStmt = StmtIt->isEmpty(); 2897 if (!RemoveStmt) 2898 RemoveStmt = isl_set_is_empty(DomainMap[Stmt.getEntryBlock()]); 2899 if (!RemoveStmt) 2900 RemoveStmt = (RemoveIgnoredStmts && isIgnored(RN, DT, LI)); 2901 2902 // Remove read only statements only after invariant loop hoisting. 2903 if (!RemoveStmt && !RemoveIgnoredStmts) { 2904 bool OnlyRead = true; 2905 for (MemoryAccess *MA : Stmt) { 2906 if (MA->isRead()) 2907 continue; 2908 2909 OnlyRead = false; 2910 break; 2911 } 2912 2913 RemoveStmt = OnlyRead; 2914 } 2915 2916 if (RemoveStmt) { 2917 // Remove the statement because it is unnecessary. 2918 if (Stmt.isRegionStmt()) 2919 for (BasicBlock *BB : Stmt.getRegion()->blocks()) 2920 StmtMap.erase(BB); 2921 else 2922 StmtMap.erase(Stmt.getBasicBlock()); 2923 2924 StmtIt = Stmts.erase(StmtIt); 2925 continue; 2926 } 2927 2928 StmtIt++; 2929 } 2930 } 2931 2932 const InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) const { 2933 LoadInst *LInst = dyn_cast<LoadInst>(Val); 2934 if (!LInst) 2935 return nullptr; 2936 2937 if (Value *Rep = InvEquivClassVMap.lookup(LInst)) 2938 LInst = cast<LoadInst>(Rep); 2939 2940 Type *Ty = LInst->getType(); 2941 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 2942 for (auto &IAClass : InvariantEquivClasses) 2943 if (PointerSCEV == std::get<0>(IAClass) && Ty == std::get<3>(IAClass)) 2944 return &IAClass; 2945 2946 return nullptr; 2947 } 2948 2949 void Scop::addInvariantLoads(ScopStmt &Stmt, MemoryAccessList &InvMAs) { 2950 2951 // Get the context under which the statement is executed. 2952 isl_set *DomainCtx = isl_set_params(Stmt.getDomain()); 2953 DomainCtx = isl_set_remove_redundancies(DomainCtx); 2954 DomainCtx = isl_set_detect_equalities(DomainCtx); 2955 DomainCtx = isl_set_coalesce(DomainCtx); 2956 2957 // Project out all parameters that relate to loads in the statement. Otherwise 2958 // we could have cyclic dependences on the constraints under which the 2959 // hoisted loads are executed and we could not determine an order in which to 2960 // pre-load them. This happens because not only lower bounds are part of the 2961 // domain but also upper bounds. 2962 for (MemoryAccess *MA : InvMAs) { 2963 Instruction *AccInst = MA->getAccessInstruction(); 2964 if (SE->isSCEVable(AccInst->getType())) { 2965 SetVector<Value *> Values; 2966 for (const SCEV *Parameter : Parameters) { 2967 Values.clear(); 2968 findValues(Parameter, Values); 2969 if (!Values.count(AccInst)) 2970 continue; 2971 2972 if (isl_id *ParamId = getIdForParam(Parameter)) { 2973 int Dim = isl_set_find_dim_by_id(DomainCtx, isl_dim_param, ParamId); 2974 DomainCtx = isl_set_eliminate(DomainCtx, isl_dim_param, Dim, 1); 2975 isl_id_free(ParamId); 2976 } 2977 } 2978 } 2979 } 2980 2981 for (MemoryAccess *MA : InvMAs) { 2982 // Check for another invariant access that accesses the same location as 2983 // MA and if found consolidate them. Otherwise create a new equivalence 2984 // class at the end of InvariantEquivClasses. 2985 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction()); 2986 Type *Ty = LInst->getType(); 2987 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 2988 2989 bool Consolidated = false; 2990 for (auto &IAClass : InvariantEquivClasses) { 2991 if (PointerSCEV != std::get<0>(IAClass) || Ty != std::get<3>(IAClass)) 2992 continue; 2993 2994 Consolidated = true; 2995 2996 // Add MA to the list of accesses that are in this class. 2997 auto &MAs = std::get<1>(IAClass); 2998 MAs.push_front(MA); 2999 3000 // Unify the execution context of the class and this statement. 3001 isl_set *&IAClassDomainCtx = std::get<2>(IAClass); 3002 if (IAClassDomainCtx) 3003 IAClassDomainCtx = isl_set_coalesce( 3004 isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx))); 3005 else 3006 IAClassDomainCtx = isl_set_copy(DomainCtx); 3007 break; 3008 } 3009 3010 if (Consolidated) 3011 continue; 3012 3013 // If we did not consolidate MA, thus did not find an equivalence class 3014 // for it, we create a new one. 3015 InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA}, 3016 isl_set_copy(DomainCtx), Ty); 3017 } 3018 3019 isl_set_free(DomainCtx); 3020 } 3021 3022 bool Scop::isHoistableAccess(MemoryAccess *Access, 3023 __isl_keep isl_union_map *Writes) { 3024 // TODO: Loads that are not loop carried, hence are in a statement with 3025 // zero iterators, are by construction invariant, though we 3026 // currently "hoist" them anyway. This is necessary because we allow 3027 // them to be treated as parameters (e.g., in conditions) and our code 3028 // generation would otherwise use the old value. 3029 3030 auto &Stmt = *Access->getStatement(); 3031 BasicBlock *BB = Stmt.getEntryBlock(); 3032 3033 if (Access->isScalarKind() || Access->isWrite() || !Access->isAffine()) 3034 return false; 3035 3036 // Skip accesses that have an invariant base pointer which is defined but 3037 // not loaded inside the SCoP. This can happened e.g., if a readnone call 3038 // returns a pointer that is used as a base address. However, as we want 3039 // to hoist indirect pointers, we allow the base pointer to be defined in 3040 // the region if it is also a memory access. Each ScopArrayInfo object 3041 // that has a base pointer origin has a base pointer that is loaded and 3042 // that it is invariant, thus it will be hoisted too. However, if there is 3043 // no base pointer origin we check that the base pointer is defined 3044 // outside the region. 3045 const ScopArrayInfo *SAI = Access->getScopArrayInfo(); 3046 auto *BasePtrInst = dyn_cast<Instruction>(SAI->getBasePtr()); 3047 if (SAI->getBasePtrOriginSAI()) { 3048 assert(BasePtrInst && R.contains(BasePtrInst)); 3049 if (!isa<LoadInst>(BasePtrInst)) 3050 return false; 3051 auto *BasePtrStmt = getStmtFor(BasePtrInst); 3052 assert(BasePtrStmt); 3053 auto *BasePtrMA = BasePtrStmt->getArrayAccessOrNULLFor(BasePtrInst); 3054 if (BasePtrMA && !isHoistableAccess(BasePtrMA, Writes)) 3055 return false; 3056 } else if (BasePtrInst && R.contains(BasePtrInst)) 3057 return false; 3058 3059 // Skip accesses in non-affine subregions as they might not be executed 3060 // under the same condition as the entry of the non-affine subregion. 3061 if (BB != Access->getAccessInstruction()->getParent()) 3062 return false; 3063 3064 isl_map *AccessRelation = Access->getAccessRelation(); 3065 3066 // Skip accesses that have an empty access relation. These can be caused 3067 // by multiple offsets with a type cast in-between that cause the overall 3068 // byte offset to be not divisible by the new types sizes. 3069 if (isl_map_is_empty(AccessRelation)) { 3070 isl_map_free(AccessRelation); 3071 return false; 3072 } 3073 3074 if (isl_map_involves_dims(AccessRelation, isl_dim_in, 0, 3075 Stmt.getNumIterators())) { 3076 isl_map_free(AccessRelation); 3077 return false; 3078 } 3079 3080 AccessRelation = isl_map_intersect_domain(AccessRelation, Stmt.getDomain()); 3081 isl_set *AccessRange = isl_map_range(AccessRelation); 3082 3083 isl_union_map *Written = isl_union_map_intersect_range( 3084 isl_union_map_copy(Writes), isl_union_set_from_set(AccessRange)); 3085 bool IsWritten = !isl_union_map_is_empty(Written); 3086 isl_union_map_free(Written); 3087 3088 if (IsWritten) 3089 return false; 3090 3091 return true; 3092 } 3093 3094 void Scop::verifyInvariantLoads(ScopDetection &SD) { 3095 auto &RIL = *SD.getRequiredInvariantLoads(&getRegion()); 3096 for (LoadInst *LI : RIL) { 3097 assert(LI && getRegion().contains(LI)); 3098 ScopStmt *Stmt = getStmtFor(LI); 3099 if (Stmt && Stmt->getArrayAccessOrNULLFor(LI)) { 3100 invalidate(INVARIANTLOAD, LI->getDebugLoc()); 3101 return; 3102 } 3103 } 3104 } 3105 3106 void Scop::hoistInvariantLoads(ScopDetection &SD) { 3107 if (PollyInvariantLoadHoisting) { 3108 isl_union_map *Writes = getWrites(); 3109 for (ScopStmt &Stmt : *this) { 3110 MemoryAccessList InvariantAccesses; 3111 3112 for (MemoryAccess *Access : Stmt) 3113 if (isHoistableAccess(Access, Writes)) 3114 InvariantAccesses.push_front(Access); 3115 3116 // We inserted invariant accesses always in the front but need them to be 3117 // sorted in a "natural order". The statements are already sorted in 3118 // reverse post order and that suffices for the accesses too. The reason 3119 // we require an order in the first place is the dependences between 3120 // invariant loads that can be caused by indirect loads. 3121 InvariantAccesses.reverse(); 3122 3123 // Transfer the memory access from the statement to the SCoP. 3124 Stmt.removeMemoryAccesses(InvariantAccesses); 3125 addInvariantLoads(Stmt, InvariantAccesses); 3126 } 3127 isl_union_map_free(Writes); 3128 } 3129 3130 verifyInvariantLoads(SD); 3131 } 3132 3133 const ScopArrayInfo * 3134 Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, 3135 ArrayRef<const SCEV *> Sizes, 3136 ScopArrayInfo::MemoryKind Kind) { 3137 auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]; 3138 if (!SAI) { 3139 auto &DL = getRegion().getEntry()->getModule()->getDataLayout(); 3140 SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind, 3141 DL, this)); 3142 } else { 3143 SAI->updateElementType(ElementType); 3144 // In case of mismatching array sizes, we bail out by setting the run-time 3145 // context to false. 3146 if (!SAI->updateSizes(Sizes)) 3147 invalidate(DELINEARIZATION, DebugLoc()); 3148 } 3149 return SAI.get(); 3150 } 3151 3152 const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, 3153 ScopArrayInfo::MemoryKind Kind) { 3154 auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get(); 3155 assert(SAI && "No ScopArrayInfo available for this base pointer"); 3156 return SAI; 3157 } 3158 3159 std::string Scop::getContextStr() const { return stringFromIslObj(Context); } 3160 3161 std::string Scop::getAssumedContextStr() const { 3162 return stringFromIslObj(AssumedContext); 3163 } 3164 3165 std::string Scop::getBoundaryContextStr() const { 3166 return stringFromIslObj(BoundaryContext); 3167 } 3168 3169 std::string Scop::getNameStr() const { 3170 std::string ExitName, EntryName; 3171 raw_string_ostream ExitStr(ExitName); 3172 raw_string_ostream EntryStr(EntryName); 3173 3174 R.getEntry()->printAsOperand(EntryStr, false); 3175 EntryStr.str(); 3176 3177 if (R.getExit()) { 3178 R.getExit()->printAsOperand(ExitStr, false); 3179 ExitStr.str(); 3180 } else 3181 ExitName = "FunctionExit"; 3182 3183 return EntryName + "---" + ExitName; 3184 } 3185 3186 __isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); } 3187 __isl_give isl_space *Scop::getParamSpace() const { 3188 return isl_set_get_space(Context); 3189 } 3190 3191 __isl_give isl_set *Scop::getAssumedContext() const { 3192 return isl_set_copy(AssumedContext); 3193 } 3194 3195 __isl_give isl_set *Scop::getRuntimeCheckContext() const { 3196 isl_set *RuntimeCheckContext = getAssumedContext(); 3197 RuntimeCheckContext = 3198 isl_set_intersect(RuntimeCheckContext, getBoundaryContext()); 3199 RuntimeCheckContext = simplifyAssumptionContext(RuntimeCheckContext, *this); 3200 return RuntimeCheckContext; 3201 } 3202 3203 bool Scop::hasFeasibleRuntimeContext() const { 3204 isl_set *RuntimeCheckContext = getRuntimeCheckContext(); 3205 RuntimeCheckContext = addNonEmptyDomainConstraints(RuntimeCheckContext); 3206 bool IsFeasible = !isl_set_is_empty(RuntimeCheckContext); 3207 isl_set_free(RuntimeCheckContext); 3208 return IsFeasible; 3209 } 3210 3211 static std::string toString(AssumptionKind Kind) { 3212 switch (Kind) { 3213 case ALIASING: 3214 return "No-aliasing"; 3215 case INBOUNDS: 3216 return "Inbounds"; 3217 case WRAPPING: 3218 return "No-overflows"; 3219 case ERRORBLOCK: 3220 return "No-error"; 3221 case INFINITELOOP: 3222 return "Finite loop"; 3223 case INVARIANTLOAD: 3224 return "Invariant load"; 3225 case DELINEARIZATION: 3226 return "Delinearization"; 3227 case ERROR_DOMAINCONJUNCTS: 3228 return "Low number of domain conjuncts"; 3229 } 3230 llvm_unreachable("Unknown AssumptionKind!"); 3231 } 3232 3233 void Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, 3234 DebugLoc Loc) { 3235 if (isl_set_is_subset(Context, Set)) 3236 return; 3237 3238 if (isl_set_is_subset(AssumedContext, Set)) 3239 return; 3240 3241 auto &F = *getRegion().getEntry()->getParent(); 3242 std::string Msg = toString(Kind) + " assumption:\t" + stringFromIslObj(Set); 3243 emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, Loc, Msg); 3244 } 3245 3246 void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, 3247 DebugLoc Loc) { 3248 trackAssumption(Kind, Set, Loc); 3249 AssumedContext = isl_set_intersect(AssumedContext, Set); 3250 3251 int NSets = isl_set_n_basic_set(AssumedContext); 3252 if (NSets >= MaxDisjunctsAssumed) { 3253 isl_space *Space = isl_set_get_space(AssumedContext); 3254 isl_set_free(AssumedContext); 3255 AssumedContext = isl_set_empty(Space); 3256 } 3257 3258 AssumedContext = isl_set_coalesce(AssumedContext); 3259 } 3260 3261 void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc) { 3262 addAssumption(Kind, isl_set_empty(getParamSpace()), Loc); 3263 } 3264 3265 __isl_give isl_set *Scop::getBoundaryContext() const { 3266 return isl_set_copy(BoundaryContext); 3267 } 3268 3269 void Scop::printContext(raw_ostream &OS) const { 3270 OS << "Context:\n"; 3271 3272 if (!Context) { 3273 OS.indent(4) << "n/a\n\n"; 3274 return; 3275 } 3276 3277 OS.indent(4) << getContextStr() << "\n"; 3278 3279 OS.indent(4) << "Assumed Context:\n"; 3280 if (!AssumedContext) { 3281 OS.indent(4) << "n/a\n\n"; 3282 return; 3283 } 3284 3285 OS.indent(4) << getAssumedContextStr() << "\n"; 3286 3287 OS.indent(4) << "Boundary Context:\n"; 3288 if (!BoundaryContext) { 3289 OS.indent(4) << "n/a\n\n"; 3290 return; 3291 } 3292 3293 OS.indent(4) << getBoundaryContextStr() << "\n"; 3294 3295 for (const SCEV *Parameter : Parameters) { 3296 int Dim = ParameterIds.find(Parameter)->second; 3297 OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n"; 3298 } 3299 } 3300 3301 void Scop::printAliasAssumptions(raw_ostream &OS) const { 3302 int noOfGroups = 0; 3303 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 3304 if (Pair.second.size() == 0) 3305 noOfGroups += 1; 3306 else 3307 noOfGroups += Pair.second.size(); 3308 } 3309 3310 OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n"; 3311 if (MinMaxAliasGroups.empty()) { 3312 OS.indent(8) << "n/a\n"; 3313 return; 3314 } 3315 3316 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 3317 3318 // If the group has no read only accesses print the write accesses. 3319 if (Pair.second.empty()) { 3320 OS.indent(8) << "[["; 3321 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 3322 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 3323 << ">"; 3324 } 3325 OS << " ]]\n"; 3326 } 3327 3328 for (const MinMaxAccessTy &MMAReadOnly : Pair.second) { 3329 OS.indent(8) << "[["; 3330 OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">"; 3331 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 3332 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 3333 << ">"; 3334 } 3335 OS << " ]]\n"; 3336 } 3337 } 3338 } 3339 3340 void Scop::printStatements(raw_ostream &OS) const { 3341 OS << "Statements {\n"; 3342 3343 for (const ScopStmt &Stmt : *this) 3344 OS.indent(4) << Stmt; 3345 3346 OS.indent(4) << "}\n"; 3347 } 3348 3349 void Scop::printArrayInfo(raw_ostream &OS) const { 3350 OS << "Arrays {\n"; 3351 3352 for (auto &Array : arrays()) 3353 Array.second->print(OS); 3354 3355 OS.indent(4) << "}\n"; 3356 3357 OS.indent(4) << "Arrays (Bounds as pw_affs) {\n"; 3358 3359 for (auto &Array : arrays()) 3360 Array.second->print(OS, /* SizeAsPwAff */ true); 3361 3362 OS.indent(4) << "}\n"; 3363 } 3364 3365 void Scop::print(raw_ostream &OS) const { 3366 OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName() 3367 << "\n"; 3368 OS.indent(4) << "Region: " << getNameStr() << "\n"; 3369 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; 3370 OS.indent(4) << "Invariant Accesses: {\n"; 3371 for (const auto &IAClass : InvariantEquivClasses) { 3372 const auto &MAs = std::get<1>(IAClass); 3373 if (MAs.empty()) { 3374 OS.indent(12) << "Class Pointer: " << *std::get<0>(IAClass) << "\n"; 3375 } else { 3376 MAs.front()->print(OS); 3377 OS.indent(12) << "Execution Context: " << std::get<2>(IAClass) << "\n"; 3378 } 3379 } 3380 OS.indent(4) << "}\n"; 3381 printContext(OS.indent(4)); 3382 printArrayInfo(OS.indent(4)); 3383 printAliasAssumptions(OS); 3384 printStatements(OS.indent(4)); 3385 } 3386 3387 void Scop::dump() const { print(dbgs()); } 3388 3389 isl_ctx *Scop::getIslCtx() const { return IslCtx.get(); } 3390 3391 __isl_give isl_pw_aff *Scop::getPwAff(const SCEV *E, BasicBlock *BB) { 3392 return Affinator.getPwAff(E, BB); 3393 } 3394 3395 __isl_give isl_union_set *Scop::getDomains() const { 3396 isl_union_set *Domain = isl_union_set_empty(getParamSpace()); 3397 3398 for (const ScopStmt &Stmt : *this) 3399 Domain = isl_union_set_add_set(Domain, Stmt.getDomain()); 3400 3401 return Domain; 3402 } 3403 3404 __isl_give isl_union_map * 3405 Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) { 3406 isl_union_map *Accesses = isl_union_map_empty(getParamSpace()); 3407 3408 for (ScopStmt &Stmt : *this) { 3409 for (MemoryAccess *MA : Stmt) { 3410 if (!Predicate(*MA)) 3411 continue; 3412 3413 isl_set *Domain = Stmt.getDomain(); 3414 isl_map *AccessDomain = MA->getAccessRelation(); 3415 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 3416 Accesses = isl_union_map_add_map(Accesses, AccessDomain); 3417 } 3418 } 3419 return isl_union_map_coalesce(Accesses); 3420 } 3421 3422 __isl_give isl_union_map *Scop::getMustWrites() { 3423 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); }); 3424 } 3425 3426 __isl_give isl_union_map *Scop::getMayWrites() { 3427 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); }); 3428 } 3429 3430 __isl_give isl_union_map *Scop::getWrites() { 3431 return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); }); 3432 } 3433 3434 __isl_give isl_union_map *Scop::getReads() { 3435 return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); }); 3436 } 3437 3438 __isl_give isl_union_map *Scop::getAccesses() { 3439 return getAccessesOfType([](MemoryAccess &MA) { return true; }); 3440 } 3441 3442 __isl_give isl_union_map *Scop::getSchedule() const { 3443 auto *Tree = getScheduleTree(); 3444 auto *S = isl_schedule_get_map(Tree); 3445 isl_schedule_free(Tree); 3446 return S; 3447 } 3448 3449 __isl_give isl_schedule *Scop::getScheduleTree() const { 3450 return isl_schedule_intersect_domain(isl_schedule_copy(Schedule), 3451 getDomains()); 3452 } 3453 3454 void Scop::setSchedule(__isl_take isl_union_map *NewSchedule) { 3455 auto *S = isl_schedule_from_domain(getDomains()); 3456 S = isl_schedule_insert_partial_schedule( 3457 S, isl_multi_union_pw_aff_from_union_map(NewSchedule)); 3458 isl_schedule_free(Schedule); 3459 Schedule = S; 3460 } 3461 3462 void Scop::setScheduleTree(__isl_take isl_schedule *NewSchedule) { 3463 isl_schedule_free(Schedule); 3464 Schedule = NewSchedule; 3465 } 3466 3467 bool Scop::restrictDomains(__isl_take isl_union_set *Domain) { 3468 bool Changed = false; 3469 for (ScopStmt &Stmt : *this) { 3470 isl_union_set *StmtDomain = isl_union_set_from_set(Stmt.getDomain()); 3471 isl_union_set *NewStmtDomain = isl_union_set_intersect( 3472 isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain)); 3473 3474 if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) { 3475 isl_union_set_free(StmtDomain); 3476 isl_union_set_free(NewStmtDomain); 3477 continue; 3478 } 3479 3480 Changed = true; 3481 3482 isl_union_set_free(StmtDomain); 3483 NewStmtDomain = isl_union_set_coalesce(NewStmtDomain); 3484 3485 if (isl_union_set_is_empty(NewStmtDomain)) { 3486 Stmt.restrictDomain(isl_set_empty(Stmt.getDomainSpace())); 3487 isl_union_set_free(NewStmtDomain); 3488 } else 3489 Stmt.restrictDomain(isl_set_from_union_set(NewStmtDomain)); 3490 } 3491 isl_union_set_free(Domain); 3492 return Changed; 3493 } 3494 3495 ScalarEvolution *Scop::getSE() const { return SE; } 3496 3497 bool Scop::isIgnored(RegionNode *RN, DominatorTree &DT, LoopInfo &LI) { 3498 BasicBlock *BB = getRegionNodeBasicBlock(RN); 3499 ScopStmt *Stmt = getStmtFor(RN); 3500 3501 // If there is no stmt, then it already has been removed. 3502 if (!Stmt) 3503 return true; 3504 3505 // Check if there are accesses contained. 3506 if (Stmt->isEmpty()) 3507 return true; 3508 3509 // Check for reachability via non-error blocks. 3510 if (!DomainMap.count(BB)) 3511 return true; 3512 3513 // Check if error blocks are contained. 3514 if (containsErrorBlock(RN, getRegion(), LI, DT)) 3515 return true; 3516 3517 return false; 3518 } 3519 3520 struct MapToDimensionDataTy { 3521 int N; 3522 isl_union_pw_multi_aff *Res; 3523 }; 3524 3525 // @brief Create a function that maps the elements of 'Set' to its N-th 3526 // dimension and add it to User->Res. 3527 // 3528 // @param Set The input set. 3529 // @param User->N The dimension to map to. 3530 // @param User->Res The isl_union_pw_multi_aff to which to add the result. 3531 // 3532 // @returns isl_stat_ok if no error occured, othewise isl_stat_error. 3533 static isl_stat mapToDimension_AddSet(__isl_take isl_set *Set, void *User) { 3534 struct MapToDimensionDataTy *Data = (struct MapToDimensionDataTy *)User; 3535 int Dim; 3536 isl_space *Space; 3537 isl_pw_multi_aff *PMA; 3538 3539 Dim = isl_set_dim(Set, isl_dim_set); 3540 Space = isl_set_get_space(Set); 3541 PMA = isl_pw_multi_aff_project_out_map(Space, isl_dim_set, Data->N, 3542 Dim - Data->N); 3543 if (Data->N > 1) 3544 PMA = isl_pw_multi_aff_drop_dims(PMA, isl_dim_out, 0, Data->N - 1); 3545 Data->Res = isl_union_pw_multi_aff_add_pw_multi_aff(Data->Res, PMA); 3546 3547 isl_set_free(Set); 3548 3549 return isl_stat_ok; 3550 } 3551 3552 // @brief Create an isl_multi_union_aff that defines an identity mapping 3553 // from the elements of USet to their N-th dimension. 3554 // 3555 // # Example: 3556 // 3557 // Domain: { A[i,j]; B[i,j,k] } 3558 // N: 1 3559 // 3560 // Resulting Mapping: { {A[i,j] -> [(j)]; B[i,j,k] -> [(j)] } 3561 // 3562 // @param USet A union set describing the elements for which to generate a 3563 // mapping. 3564 // @param N The dimension to map to. 3565 // @returns A mapping from USet to its N-th dimension. 3566 static __isl_give isl_multi_union_pw_aff * 3567 mapToDimension(__isl_take isl_union_set *USet, int N) { 3568 assert(N >= 0); 3569 assert(USet); 3570 assert(!isl_union_set_is_empty(USet)); 3571 3572 struct MapToDimensionDataTy Data; 3573 3574 auto *Space = isl_union_set_get_space(USet); 3575 auto *PwAff = isl_union_pw_multi_aff_empty(Space); 3576 3577 Data = {N, PwAff}; 3578 3579 auto Res = isl_union_set_foreach_set(USet, &mapToDimension_AddSet, &Data); 3580 (void)Res; 3581 3582 assert(Res == isl_stat_ok); 3583 3584 isl_union_set_free(USet); 3585 return isl_multi_union_pw_aff_from_union_pw_multi_aff(Data.Res); 3586 } 3587 3588 void Scop::addScopStmt(BasicBlock *BB, Region *R) { 3589 if (BB) { 3590 Stmts.emplace_back(*this, *BB); 3591 auto *Stmt = &Stmts.back(); 3592 StmtMap[BB] = Stmt; 3593 } else { 3594 assert(R && "Either basic block or a region expected."); 3595 Stmts.emplace_back(*this, *R); 3596 auto *Stmt = &Stmts.back(); 3597 for (BasicBlock *BB : R->blocks()) 3598 StmtMap[BB] = Stmt; 3599 } 3600 } 3601 3602 void Scop::buildSchedule(ScopDetection &SD, LoopInfo &LI) { 3603 Loop *L = getLoopSurroundingRegion(getRegion(), LI); 3604 LoopStackTy LoopStack({LoopStackElementTy(L, nullptr, 0)}); 3605 buildSchedule(getRegion().getNode(), LoopStack, SD, LI); 3606 assert(LoopStack.size() == 1 && LoopStack.back().L == L); 3607 Schedule = LoopStack[0].Schedule; 3608 } 3609 3610 /// To generate a schedule for the elements in a Region we traverse the Region 3611 /// in reverse-post-order and add the contained RegionNodes in traversal order 3612 /// to the schedule of the loop that is currently at the top of the LoopStack. 3613 /// For loop-free codes, this results in a correct sequential ordering. 3614 /// 3615 /// Example: 3616 /// bb1(0) 3617 /// / \. 3618 /// bb2(1) bb3(2) 3619 /// \ / \. 3620 /// bb4(3) bb5(4) 3621 /// \ / 3622 /// bb6(5) 3623 /// 3624 /// Including loops requires additional processing. Whenever a loop header is 3625 /// encountered, the corresponding loop is added to the @p LoopStack. Starting 3626 /// from an empty schedule, we first process all RegionNodes that are within 3627 /// this loop and complete the sequential schedule at this loop-level before 3628 /// processing about any other nodes. To implement this 3629 /// loop-nodes-first-processing, the reverse post-order traversal is 3630 /// insufficient. Hence, we additionally check if the traversal yields 3631 /// sub-regions or blocks that are outside the last loop on the @p LoopStack. 3632 /// These region-nodes are then queue and only traverse after the all nodes 3633 /// within the current loop have been processed. 3634 void Scop::buildSchedule(Region *R, LoopStackTy &LoopStack, ScopDetection &SD, 3635 LoopInfo &LI) { 3636 Loop *OuterScopLoop = getLoopSurroundingRegion(getRegion(), LI); 3637 3638 ReversePostOrderTraversal<Region *> RTraversal(R); 3639 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end()); 3640 std::deque<RegionNode *> DelayList; 3641 bool LastRNWaiting = false; 3642 3643 // Iterate over the region @p R in reverse post-order but queue 3644 // sub-regions/blocks iff they are not part of the last encountered but not 3645 // completely traversed loop. The variable LastRNWaiting is a flag to indicate 3646 // that we queued the last sub-region/block from the reverse post-order 3647 // iterator. If it is set we have to explore the next sub-region/block from 3648 // the iterator (if any) to guarantee progress. If it is not set we first try 3649 // the next queued sub-region/blocks. 3650 while (!WorkList.empty() || !DelayList.empty()) { 3651 RegionNode *RN; 3652 3653 if ((LastRNWaiting && !WorkList.empty()) || DelayList.size() == 0) { 3654 RN = WorkList.front(); 3655 WorkList.pop_front(); 3656 LastRNWaiting = false; 3657 } else { 3658 RN = DelayList.front(); 3659 DelayList.pop_front(); 3660 } 3661 3662 Loop *L = getRegionNodeLoop(RN, LI); 3663 if (!getRegion().contains(L)) 3664 L = OuterScopLoop; 3665 3666 Loop *LastLoop = LoopStack.back().L; 3667 if (LastLoop != L) { 3668 if (!LastLoop->contains(L)) { 3669 LastRNWaiting = true; 3670 DelayList.push_back(RN); 3671 continue; 3672 } 3673 LoopStack.push_back({L, nullptr, 0}); 3674 } 3675 buildSchedule(RN, LoopStack, SD, LI); 3676 } 3677 3678 return; 3679 } 3680 3681 void Scop::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack, 3682 ScopDetection &SD, LoopInfo &LI) { 3683 3684 if (RN->isSubRegion()) { 3685 auto *LocalRegion = RN->getNodeAs<Region>(); 3686 if (!SD.isNonAffineSubRegion(LocalRegion, &getRegion())) { 3687 buildSchedule(LocalRegion, LoopStack, SD, LI); 3688 return; 3689 } 3690 } 3691 3692 auto &LoopData = LoopStack.back(); 3693 LoopData.NumBlocksProcessed += getNumBlocksInRegionNode(RN); 3694 3695 if (auto *Stmt = getStmtFor(RN)) { 3696 auto *UDomain = isl_union_set_from_set(Stmt->getDomain()); 3697 auto *StmtSchedule = isl_schedule_from_domain(UDomain); 3698 LoopData.Schedule = combineInSequence(LoopData.Schedule, StmtSchedule); 3699 } 3700 3701 // Check if we just processed the last node in this loop. If we did, finalize 3702 // the loop by: 3703 // 3704 // - adding new schedule dimensions 3705 // - folding the resulting schedule into the parent loop schedule 3706 // - dropping the loop schedule from the LoopStack. 3707 // 3708 // Then continue to check surrounding loops, which might also have been 3709 // completed by this node. 3710 while (LoopData.L && 3711 LoopData.NumBlocksProcessed == LoopData.L->getNumBlocks()) { 3712 auto *Schedule = LoopData.Schedule; 3713 auto NumBlocksProcessed = LoopData.NumBlocksProcessed; 3714 3715 LoopStack.pop_back(); 3716 auto &NextLoopData = LoopStack.back(); 3717 3718 if (Schedule) { 3719 auto *Domain = isl_schedule_get_domain(Schedule); 3720 auto *MUPA = mapToDimension(Domain, LoopStack.size()); 3721 Schedule = isl_schedule_insert_partial_schedule(Schedule, MUPA); 3722 NextLoopData.Schedule = 3723 combineInSequence(NextLoopData.Schedule, Schedule); 3724 } 3725 3726 NextLoopData.NumBlocksProcessed += NumBlocksProcessed; 3727 LoopData = NextLoopData; 3728 } 3729 } 3730 3731 ScopStmt *Scop::getStmtFor(BasicBlock *BB) const { 3732 auto StmtMapIt = StmtMap.find(BB); 3733 if (StmtMapIt == StmtMap.end()) 3734 return nullptr; 3735 return StmtMapIt->second; 3736 } 3737 3738 ScopStmt *Scop::getStmtFor(RegionNode *RN) const { 3739 if (RN->isSubRegion()) 3740 return getStmtFor(RN->getNodeAs<Region>()); 3741 return getStmtFor(RN->getNodeAs<BasicBlock>()); 3742 } 3743 3744 ScopStmt *Scop::getStmtFor(Region *R) const { 3745 ScopStmt *Stmt = getStmtFor(R->getEntry()); 3746 assert(!Stmt || Stmt->getRegion() == R); 3747 return Stmt; 3748 } 3749 3750 int Scop::getRelativeLoopDepth(const Loop *L) const { 3751 Loop *OuterLoop = 3752 L ? R.outermostLoopInRegion(const_cast<Loop *>(L)) : nullptr; 3753 if (!OuterLoop) 3754 return -1; 3755 return L->getLoopDepth() - OuterLoop->getLoopDepth(); 3756 } 3757 3758 void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R, 3759 Region *NonAffineSubRegion, bool IsExitBlock) { 3760 3761 // PHI nodes that are in the exit block of the region, hence if IsExitBlock is 3762 // true, are not modeled as ordinary PHI nodes as they are not part of the 3763 // region. However, we model the operands in the predecessor blocks that are 3764 // part of the region as regular scalar accesses. 3765 3766 // If we can synthesize a PHI we can skip it, however only if it is in 3767 // the region. If it is not it can only be in the exit block of the region. 3768 // In this case we model the operands but not the PHI itself. 3769 if (!IsExitBlock && canSynthesize(PHI, LI, SE, &R)) 3770 return; 3771 3772 // PHI nodes are modeled as if they had been demoted prior to the SCoP 3773 // detection. Hence, the PHI is a load of a new memory location in which the 3774 // incoming value was written at the end of the incoming basic block. 3775 bool OnlyNonAffineSubRegionOperands = true; 3776 for (unsigned u = 0; u < PHI->getNumIncomingValues(); u++) { 3777 Value *Op = PHI->getIncomingValue(u); 3778 BasicBlock *OpBB = PHI->getIncomingBlock(u); 3779 3780 // Do not build scalar dependences inside a non-affine subregion. 3781 if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB)) 3782 continue; 3783 3784 OnlyNonAffineSubRegionOperands = false; 3785 ensurePHIWrite(PHI, OpBB, Op, IsExitBlock); 3786 } 3787 3788 if (!OnlyNonAffineSubRegionOperands && !IsExitBlock) { 3789 addPHIReadAccess(PHI); 3790 } 3791 } 3792 3793 void ScopInfo::buildScalarDependences(Instruction *Inst) { 3794 assert(!isa<PHINode>(Inst)); 3795 3796 // Pull-in required operands. 3797 for (Use &Op : Inst->operands()) 3798 ensureValueRead(Op.get(), Inst->getParent()); 3799 } 3800 3801 void ScopInfo::buildEscapingDependences(Instruction *Inst) { 3802 Region *R = &scop->getRegion(); 3803 3804 // Check for uses of this instruction outside the scop. Because we do not 3805 // iterate over such instructions and therefore did not "ensure" the existence 3806 // of a write, we must determine such use here. 3807 for (Use &U : Inst->uses()) { 3808 Instruction *UI = dyn_cast<Instruction>(U.getUser()); 3809 if (!UI) 3810 continue; 3811 3812 BasicBlock *UseParent = getUseBlock(U); 3813 BasicBlock *UserParent = UI->getParent(); 3814 3815 // An escaping value is either used by an instruction not within the scop, 3816 // or (when the scop region's exit needs to be simplified) by a PHI in the 3817 // scop's exit block. This is because region simplification before code 3818 // generation inserts new basic blocks before the PHI such that its incoming 3819 // blocks are not in the scop anymore. 3820 if (!R->contains(UseParent) || 3821 (isa<PHINode>(UI) && UserParent == R->getExit() && 3822 R->getExitingBlock())) { 3823 // At least one escaping use found. 3824 ensureValueWrite(Inst); 3825 break; 3826 } 3827 } 3828 } 3829 3830 bool ScopInfo::buildAccessMultiDimFixed( 3831 MemAccInst Inst, Loop *L, Region *R, 3832 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3833 const InvariantLoadsSetTy &ScopRIL) { 3834 Value *Val = Inst.getValueOperand(); 3835 Type *ElementType = Val->getType(); 3836 Value *Address = Inst.getPointerOperand(); 3837 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); 3838 const SCEVUnknown *BasePointer = 3839 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction)); 3840 enum MemoryAccess::AccessType Type = 3841 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; 3842 3843 if (auto *BitCast = dyn_cast<BitCastInst>(Address)) { 3844 auto *Src = BitCast->getOperand(0); 3845 auto *SrcTy = Src->getType(); 3846 auto *DstTy = BitCast->getType(); 3847 if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits()) 3848 Address = Src; 3849 } 3850 3851 auto *GEP = dyn_cast<GetElementPtrInst>(Address); 3852 if (!GEP) 3853 return false; 3854 3855 std::vector<const SCEV *> Subscripts; 3856 std::vector<int> Sizes; 3857 std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP, *SE); 3858 auto *BasePtr = GEP->getOperand(0); 3859 3860 std::vector<const SCEV *> SizesSCEV; 3861 3862 for (auto *Subscript : Subscripts) { 3863 InvariantLoadsSetTy AccessILS; 3864 if (!isAffineExpr(R, Subscript, *SE, nullptr, &AccessILS)) 3865 return false; 3866 3867 for (LoadInst *LInst : AccessILS) 3868 if (!ScopRIL.count(LInst)) 3869 return false; 3870 } 3871 3872 if (Sizes.empty()) 3873 return false; 3874 3875 for (auto V : Sizes) 3876 SizesSCEV.push_back(SE->getSCEV( 3877 ConstantInt::get(IntegerType::getInt64Ty(BasePtr->getContext()), V))); 3878 3879 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementType, true, 3880 Subscripts, SizesSCEV, Val); 3881 return true; 3882 } 3883 3884 bool ScopInfo::buildAccessMultiDimParam( 3885 MemAccInst Inst, Loop *L, Region *R, 3886 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3887 const InvariantLoadsSetTy &ScopRIL, const MapInsnToMemAcc &InsnToMemAcc) { 3888 if (!PollyDelinearize) 3889 return false; 3890 3891 Value *Address = Inst.getPointerOperand(); 3892 Value *Val = Inst.getValueOperand(); 3893 Type *ElementType = Val->getType(); 3894 unsigned ElementSize = DL->getTypeAllocSize(ElementType); 3895 enum MemoryAccess::AccessType Type = 3896 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; 3897 3898 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); 3899 const SCEVUnknown *BasePointer = 3900 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction)); 3901 3902 assert(BasePointer && "Could not find base pointer"); 3903 AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer); 3904 3905 auto AccItr = InsnToMemAcc.find(Inst); 3906 if (AccItr == InsnToMemAcc.end()) 3907 return false; 3908 3909 std::vector<const SCEV *> Sizes( 3910 AccItr->second.Shape->DelinearizedSizes.begin(), 3911 AccItr->second.Shape->DelinearizedSizes.end()); 3912 // Remove the element size. This information is already provided by the 3913 // ElementSize parameter. In case the element size of this access and the 3914 // element size used for delinearization differs the delinearization is 3915 // incorrect. Hence, we invalidate the scop. 3916 // 3917 // TODO: Handle delinearization with differing element sizes. 3918 auto DelinearizedSize = 3919 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue(); 3920 Sizes.pop_back(); 3921 if (ElementSize != DelinearizedSize) 3922 scop->invalidate(DELINEARIZATION, Inst->getDebugLoc()); 3923 3924 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementType, true, 3925 AccItr->second.DelinearizedSubscripts, Sizes, Val); 3926 return true; 3927 } 3928 3929 bool ScopInfo::buildAccessMemIntrinsic( 3930 MemAccInst Inst, Loop *L, Region *R, 3931 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3932 const InvariantLoadsSetTy &ScopRIL) { 3933 auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst); 3934 3935 if (MemIntr == nullptr) 3936 return false; 3937 3938 auto *LengthVal = SE->getSCEVAtScope(MemIntr->getLength(), L); 3939 assert(LengthVal); 3940 3941 // Check if the length val is actually affine or if we overapproximate it 3942 InvariantLoadsSetTy AccessILS; 3943 bool LengthIsAffine = isAffineExpr(R, LengthVal, *SE, nullptr, &AccessILS); 3944 for (LoadInst *LInst : AccessILS) 3945 if (!ScopRIL.count(LInst)) 3946 LengthIsAffine = false; 3947 if (!LengthIsAffine) 3948 LengthVal = nullptr; 3949 3950 auto *DestPtrVal = MemIntr->getDest(); 3951 assert(DestPtrVal); 3952 auto *DestAccFunc = SE->getSCEVAtScope(DestPtrVal, L); 3953 assert(DestAccFunc); 3954 auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(SE->getPointerBase(DestAccFunc)); 3955 assert(DestPtrSCEV); 3956 DestAccFunc = SE->getMinusSCEV(DestAccFunc, DestPtrSCEV); 3957 addArrayAccess(Inst, MemoryAccess::MUST_WRITE, DestPtrSCEV->getValue(), 3958 IntegerType::getInt8Ty(DestPtrVal->getContext()), false, 3959 {DestAccFunc, LengthVal}, {}, Inst.getValueOperand()); 3960 3961 auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr); 3962 if (!MemTrans) 3963 return true; 3964 3965 auto *SrcPtrVal = MemTrans->getSource(); 3966 assert(SrcPtrVal); 3967 auto *SrcAccFunc = SE->getSCEVAtScope(SrcPtrVal, L); 3968 assert(SrcAccFunc); 3969 auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(SE->getPointerBase(SrcAccFunc)); 3970 assert(SrcPtrSCEV); 3971 SrcAccFunc = SE->getMinusSCEV(SrcAccFunc, SrcPtrSCEV); 3972 addArrayAccess(Inst, MemoryAccess::READ, SrcPtrSCEV->getValue(), 3973 IntegerType::getInt8Ty(SrcPtrVal->getContext()), false, 3974 {SrcAccFunc, LengthVal}, {}, Inst.getValueOperand()); 3975 3976 return true; 3977 } 3978 3979 bool ScopInfo::buildAccessCallInst( 3980 MemAccInst Inst, Loop *L, Region *R, 3981 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3982 const InvariantLoadsSetTy &ScopRIL) { 3983 auto *CI = dyn_cast_or_null<CallInst>(Inst); 3984 3985 if (CI == nullptr) 3986 return false; 3987 3988 if (CI->doesNotAccessMemory() || isIgnoredIntrinsic(CI)) 3989 return true; 3990 3991 bool ReadOnly = false; 3992 auto *AF = SE->getConstant(IntegerType::getInt64Ty(CI->getContext()), 0); 3993 auto *CalledFunction = CI->getCalledFunction(); 3994 switch (AA->getModRefBehavior(CalledFunction)) { 3995 case llvm::FMRB_UnknownModRefBehavior: 3996 llvm_unreachable("Unknown mod ref behaviour cannot be represented."); 3997 case llvm::FMRB_DoesNotAccessMemory: 3998 return true; 3999 case llvm::FMRB_OnlyReadsMemory: 4000 GlobalReads.push_back(CI); 4001 return true; 4002 case llvm::FMRB_OnlyReadsArgumentPointees: 4003 ReadOnly = true; 4004 // Fall through 4005 case llvm::FMRB_OnlyAccessesArgumentPointees: 4006 auto AccType = ReadOnly ? MemoryAccess::READ : MemoryAccess::MAY_WRITE; 4007 for (const auto &Arg : CI->arg_operands()) { 4008 if (!Arg->getType()->isPointerTy()) 4009 continue; 4010 4011 auto *ArgSCEV = SE->getSCEVAtScope(Arg, L); 4012 if (ArgSCEV->isZero()) 4013 continue; 4014 4015 auto *ArgBasePtr = cast<SCEVUnknown>(SE->getPointerBase(ArgSCEV)); 4016 addArrayAccess(Inst, AccType, ArgBasePtr->getValue(), 4017 ArgBasePtr->getType(), false, {AF}, {}, CI); 4018 } 4019 return true; 4020 } 4021 4022 return true; 4023 } 4024 4025 void ScopInfo::buildAccessSingleDim( 4026 MemAccInst Inst, Loop *L, Region *R, 4027 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 4028 const InvariantLoadsSetTy &ScopRIL) { 4029 Value *Address = Inst.getPointerOperand(); 4030 Value *Val = Inst.getValueOperand(); 4031 Type *ElementType = Val->getType(); 4032 enum MemoryAccess::AccessType Type = 4033 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; 4034 4035 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); 4036 const SCEVUnknown *BasePointer = 4037 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction)); 4038 4039 assert(BasePointer && "Could not find base pointer"); 4040 AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer); 4041 4042 // Check if the access depends on a loop contained in a non-affine subregion. 4043 bool isVariantInNonAffineLoop = false; 4044 if (BoxedLoops) { 4045 SetVector<const Loop *> Loops; 4046 findLoops(AccessFunction, Loops); 4047 for (const Loop *L : Loops) 4048 if (BoxedLoops->count(L)) 4049 isVariantInNonAffineLoop = true; 4050 } 4051 4052 InvariantLoadsSetTy AccessILS; 4053 bool IsAffine = 4054 !isVariantInNonAffineLoop && 4055 isAffineExpr(R, AccessFunction, *SE, BasePointer->getValue(), &AccessILS); 4056 4057 for (LoadInst *LInst : AccessILS) 4058 if (!ScopRIL.count(LInst)) 4059 IsAffine = false; 4060 4061 if (!IsAffine && Type == MemoryAccess::MUST_WRITE) 4062 Type = MemoryAccess::MAY_WRITE; 4063 4064 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementType, IsAffine, 4065 {AccessFunction}, {}, Val); 4066 } 4067 4068 void ScopInfo::buildMemoryAccess( 4069 MemAccInst Inst, Loop *L, Region *R, 4070 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 4071 const InvariantLoadsSetTy &ScopRIL, const MapInsnToMemAcc &InsnToMemAcc) { 4072 4073 if (buildAccessMemIntrinsic(Inst, L, R, BoxedLoops, ScopRIL)) 4074 return; 4075 4076 if (buildAccessCallInst(Inst, L, R, BoxedLoops, ScopRIL)) 4077 return; 4078 4079 if (buildAccessMultiDimFixed(Inst, L, R, BoxedLoops, ScopRIL)) 4080 return; 4081 4082 if (buildAccessMultiDimParam(Inst, L, R, BoxedLoops, ScopRIL, InsnToMemAcc)) 4083 return; 4084 4085 buildAccessSingleDim(Inst, L, R, BoxedLoops, ScopRIL); 4086 } 4087 4088 void ScopInfo::buildAccessFunctions(Region &R, Region &SR, 4089 const MapInsnToMemAcc &InsnToMemAcc) { 4090 4091 if (SD->isNonAffineSubRegion(&SR, &R)) { 4092 for (BasicBlock *BB : SR.blocks()) 4093 buildAccessFunctions(R, *BB, InsnToMemAcc, &SR); 4094 return; 4095 } 4096 4097 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I) 4098 if (I->isSubRegion()) 4099 buildAccessFunctions(R, *I->getNodeAs<Region>(), InsnToMemAcc); 4100 else 4101 buildAccessFunctions(R, *I->getNodeAs<BasicBlock>(), InsnToMemAcc); 4102 } 4103 4104 void ScopInfo::buildStmts(Region &R, Region &SR) { 4105 4106 if (SD->isNonAffineSubRegion(&SR, &R)) { 4107 scop->addScopStmt(nullptr, &SR); 4108 return; 4109 } 4110 4111 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I) 4112 if (I->isSubRegion()) 4113 buildStmts(R, *I->getNodeAs<Region>()); 4114 else 4115 scop->addScopStmt(I->getNodeAs<BasicBlock>(), nullptr); 4116 } 4117 4118 void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB, 4119 const MapInsnToMemAcc &InsnToMemAcc, 4120 Region *NonAffineSubRegion, 4121 bool IsExitBlock) { 4122 // We do not build access functions for error blocks, as they may contain 4123 // instructions we can not model. 4124 if (isErrorBlock(BB, R, *LI, *DT) && !IsExitBlock) 4125 return; 4126 4127 Loop *L = LI->getLoopFor(&BB); 4128 4129 // The set of loops contained in non-affine subregions that are part of R. 4130 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD->getBoxedLoops(&R); 4131 4132 // The set of loads that are required to be invariant. 4133 auto &ScopRIL = *SD->getRequiredInvariantLoads(&R); 4134 4135 for (Instruction &Inst : BB) { 4136 PHINode *PHI = dyn_cast<PHINode>(&Inst); 4137 if (PHI) 4138 buildPHIAccesses(PHI, R, NonAffineSubRegion, IsExitBlock); 4139 4140 // For the exit block we stop modeling after the last PHI node. 4141 if (!PHI && IsExitBlock) 4142 break; 4143 4144 // TODO: At this point we only know that elements of ScopRIL have to be 4145 // invariant and will be hoisted for the SCoP to be processed. Though, 4146 // there might be other invariant accesses that will be hoisted and 4147 // that would allow to make a non-affine access affine. 4148 if (auto MemInst = MemAccInst::dyn_cast(Inst)) 4149 buildMemoryAccess(MemInst, L, &R, BoxedLoops, ScopRIL, InsnToMemAcc); 4150 4151 if (isIgnoredIntrinsic(&Inst)) 4152 continue; 4153 4154 if (!PHI) 4155 buildScalarDependences(&Inst); 4156 if (!IsExitBlock) 4157 buildEscapingDependences(&Inst); 4158 } 4159 } 4160 4161 MemoryAccess *ScopInfo::addMemoryAccess(BasicBlock *BB, Instruction *Inst, 4162 MemoryAccess::AccessType AccType, 4163 Value *BaseAddress, Type *ElementType, 4164 bool Affine, Value *AccessValue, 4165 ArrayRef<const SCEV *> Subscripts, 4166 ArrayRef<const SCEV *> Sizes, 4167 ScopArrayInfo::MemoryKind Kind) { 4168 ScopStmt *Stmt = scop->getStmtFor(BB); 4169 4170 // Do not create a memory access for anything not in the SCoP. It would be 4171 // ignored anyway. 4172 if (!Stmt) 4173 return nullptr; 4174 4175 AccFuncSetType &AccList = scop->getOrCreateAccessFunctions(BB); 4176 Value *BaseAddr = BaseAddress; 4177 std::string BaseName = getIslCompatibleName("MemRef_", BaseAddr, ""); 4178 4179 bool isKnownMustAccess = false; 4180 4181 // Accesses in single-basic block statements are always excuted. 4182 if (Stmt->isBlockStmt()) 4183 isKnownMustAccess = true; 4184 4185 if (Stmt->isRegionStmt()) { 4186 // Accesses that dominate the exit block of a non-affine region are always 4187 // executed. In non-affine regions there may exist MK_Values that do not 4188 // dominate the exit. MK_Values will always dominate the exit and MK_PHIs 4189 // only if there is at most one PHI_WRITE in the non-affine region. 4190 if (DT->dominates(BB, Stmt->getRegion()->getExit())) 4191 isKnownMustAccess = true; 4192 } 4193 4194 // Non-affine PHI writes do not "happen" at a particular instruction, but 4195 // after exiting the statement. Therefore they are guaranteed execute and 4196 // overwrite the old value. 4197 if (Kind == ScopArrayInfo::MK_PHI || Kind == ScopArrayInfo::MK_ExitPHI) 4198 isKnownMustAccess = true; 4199 4200 if (!isKnownMustAccess && AccType == MemoryAccess::MUST_WRITE) 4201 AccType = MemoryAccess::MAY_WRITE; 4202 4203 AccList.emplace_back(Stmt, Inst, AccType, BaseAddress, ElementType, Affine, 4204 Subscripts, Sizes, AccessValue, Kind, BaseName); 4205 Stmt->addAccess(&AccList.back()); 4206 return &AccList.back(); 4207 } 4208 4209 void ScopInfo::addArrayAccess(MemAccInst MemAccInst, 4210 MemoryAccess::AccessType AccType, 4211 Value *BaseAddress, Type *ElementType, 4212 bool IsAffine, ArrayRef<const SCEV *> Subscripts, 4213 ArrayRef<const SCEV *> Sizes, 4214 Value *AccessValue) { 4215 ArrayBasePointers.insert(BaseAddress); 4216 addMemoryAccess(MemAccInst->getParent(), MemAccInst, AccType, BaseAddress, 4217 ElementType, IsAffine, AccessValue, Subscripts, Sizes, 4218 ScopArrayInfo::MK_Array); 4219 } 4220 4221 void ScopInfo::ensureValueWrite(Instruction *Inst) { 4222 ScopStmt *Stmt = scop->getStmtFor(Inst); 4223 4224 // Inst not defined within this SCoP. 4225 if (!Stmt) 4226 return; 4227 4228 // Do not process further if the instruction is already written. 4229 if (Stmt->lookupValueWriteOf(Inst)) 4230 return; 4231 4232 addMemoryAccess(Inst->getParent(), Inst, MemoryAccess::MUST_WRITE, Inst, 4233 Inst->getType(), true, Inst, ArrayRef<const SCEV *>(), 4234 ArrayRef<const SCEV *>(), ScopArrayInfo::MK_Value); 4235 } 4236 4237 void ScopInfo::ensureValueRead(Value *V, BasicBlock *UserBB) { 4238 4239 // There cannot be an "access" for literal constants. BasicBlock references 4240 // (jump destinations) also never change. 4241 if ((isa<Constant>(V) && !isa<GlobalVariable>(V)) || isa<BasicBlock>(V)) 4242 return; 4243 4244 // If the instruction can be synthesized and the user is in the region we do 4245 // not need to add a value dependences. 4246 Region &ScopRegion = scop->getRegion(); 4247 if (canSynthesize(V, LI, SE, &ScopRegion)) 4248 return; 4249 4250 // Do not build scalar dependences for required invariant loads as we will 4251 // hoist them later on anyway or drop the SCoP if we cannot. 4252 auto *ScopRIL = SD->getRequiredInvariantLoads(&ScopRegion); 4253 if (ScopRIL->count(dyn_cast<LoadInst>(V))) 4254 return; 4255 4256 // Determine the ScopStmt containing the value's definition and use. There is 4257 // no defining ScopStmt if the value is a function argument, a global value, 4258 // or defined outside the SCoP. 4259 Instruction *ValueInst = dyn_cast<Instruction>(V); 4260 ScopStmt *ValueStmt = ValueInst ? scop->getStmtFor(ValueInst) : nullptr; 4261 4262 ScopStmt *UserStmt = scop->getStmtFor(UserBB); 4263 4264 // We do not model uses outside the scop. 4265 if (!UserStmt) 4266 return; 4267 4268 // Add MemoryAccess for invariant values only if requested. 4269 if (!ModelReadOnlyScalars && !ValueStmt) 4270 return; 4271 4272 // Ignore use-def chains within the same ScopStmt. 4273 if (ValueStmt == UserStmt) 4274 return; 4275 4276 // Do not create another MemoryAccess for reloading the value if one already 4277 // exists. 4278 if (UserStmt->lookupValueReadOf(V)) 4279 return; 4280 4281 addMemoryAccess(UserBB, nullptr, MemoryAccess::READ, V, V->getType(), true, V, 4282 ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(), 4283 ScopArrayInfo::MK_Value); 4284 if (ValueInst) 4285 ensureValueWrite(ValueInst); 4286 } 4287 4288 void ScopInfo::ensurePHIWrite(PHINode *PHI, BasicBlock *IncomingBlock, 4289 Value *IncomingValue, bool IsExitBlock) { 4290 ScopStmt *IncomingStmt = scop->getStmtFor(IncomingBlock); 4291 if (!IncomingStmt) 4292 return; 4293 4294 // Take care for the incoming value being available in the incoming block. 4295 // This must be done before the check for multiple PHI writes because multiple 4296 // exiting edges from subregion each can be the effective written value of the 4297 // subregion. As such, all of them must be made available in the subregion 4298 // statement. 4299 ensureValueRead(IncomingValue, IncomingBlock); 4300 4301 // Do not add more than one MemoryAccess per PHINode and ScopStmt. 4302 if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) { 4303 assert(Acc->getAccessInstruction() == PHI); 4304 Acc->addIncoming(IncomingBlock, IncomingValue); 4305 return; 4306 } 4307 4308 MemoryAccess *Acc = addMemoryAccess( 4309 IncomingStmt->getEntryBlock(), PHI, MemoryAccess::MUST_WRITE, PHI, 4310 PHI->getType(), true, PHI, ArrayRef<const SCEV *>(), 4311 ArrayRef<const SCEV *>(), 4312 IsExitBlock ? ScopArrayInfo::MK_ExitPHI : ScopArrayInfo::MK_PHI); 4313 assert(Acc); 4314 Acc->addIncoming(IncomingBlock, IncomingValue); 4315 } 4316 4317 void ScopInfo::addPHIReadAccess(PHINode *PHI) { 4318 addMemoryAccess(PHI->getParent(), PHI, MemoryAccess::READ, PHI, 4319 PHI->getType(), true, PHI, ArrayRef<const SCEV *>(), 4320 ArrayRef<const SCEV *>(), ScopArrayInfo::MK_PHI); 4321 } 4322 4323 void ScopInfo::buildScop(Region &R, AssumptionCache &AC) { 4324 unsigned MaxLoopDepth = getMaxLoopDepthInRegion(R, *LI, *SD); 4325 scop.reset(new Scop(R, *SE, MaxLoopDepth)); 4326 4327 buildStmts(R, R); 4328 buildAccessFunctions(R, R, *SD->getInsnToMemAccMap(&R)); 4329 4330 // In case the region does not have an exiting block we will later (during 4331 // code generation) split the exit block. This will move potential PHI nodes 4332 // from the current exit block into the new region exiting block. Hence, PHI 4333 // nodes that are at this point not part of the region will be. 4334 // To handle these PHI nodes later we will now model their operands as scalar 4335 // accesses. Note that we do not model anything in the exit block if we have 4336 // an exiting block in the region, as there will not be any splitting later. 4337 if (!R.getExitingBlock()) 4338 buildAccessFunctions(R, *R.getExit(), *SD->getInsnToMemAccMap(&R), nullptr, 4339 /* IsExitBlock */ true); 4340 4341 // Create memory accesses for global reads since all arrays are now known. 4342 auto *AF = SE->getConstant(IntegerType::getInt64Ty(SE->getContext()), 0); 4343 for (auto *GlobalRead : GlobalReads) 4344 for (auto *BP : ArrayBasePointers) 4345 addArrayAccess(MemAccInst(GlobalRead), MemoryAccess::READ, BP, 4346 BP->getType(), false, {AF}, {}, GlobalRead); 4347 4348 scop->init(*AA, AC, *SD, *DT, *LI); 4349 } 4350 4351 void ScopInfo::print(raw_ostream &OS, const Module *) const { 4352 if (!scop) { 4353 OS << "Invalid Scop!\n"; 4354 return; 4355 } 4356 4357 scop->print(OS); 4358 } 4359 4360 void ScopInfo::clear() { scop.reset(); } 4361 4362 //===----------------------------------------------------------------------===// 4363 ScopInfo::ScopInfo() : RegionPass(ID) {} 4364 4365 ScopInfo::~ScopInfo() { clear(); } 4366 4367 void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const { 4368 AU.addRequired<LoopInfoWrapperPass>(); 4369 AU.addRequired<RegionInfoPass>(); 4370 AU.addRequired<DominatorTreeWrapperPass>(); 4371 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 4372 AU.addRequiredTransitive<ScopDetection>(); 4373 AU.addRequired<AAResultsWrapperPass>(); 4374 AU.addRequired<AssumptionCacheTracker>(); 4375 AU.setPreservesAll(); 4376 } 4377 4378 bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) { 4379 SD = &getAnalysis<ScopDetection>(); 4380 4381 if (!SD->isMaxRegionInScop(*R)) 4382 return false; 4383 4384 Function *F = R->getEntry()->getParent(); 4385 SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 4386 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 4387 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); 4388 DL = &F->getParent()->getDataLayout(); 4389 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 4390 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F); 4391 4392 DebugLoc Beg, End; 4393 getDebugLocations(R, Beg, End); 4394 std::string Msg = "SCoP begins here."; 4395 emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, Beg, Msg); 4396 4397 buildScop(*R, AC); 4398 4399 DEBUG(scop->print(dbgs())); 4400 4401 if (scop->isEmpty() || !scop->hasFeasibleRuntimeContext()) { 4402 Msg = "SCoP ends here but was dismissed."; 4403 scop.reset(); 4404 } else { 4405 Msg = "SCoP ends here."; 4406 ++ScopFound; 4407 if (scop->getMaxLoopDepth() > 0) 4408 ++RichScopFound; 4409 } 4410 4411 emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, End, Msg); 4412 4413 return false; 4414 } 4415 4416 char ScopInfo::ID = 0; 4417 4418 Pass *polly::createScopInfoPass() { return new ScopInfo(); } 4419 4420 INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops", 4421 "Polly - Create polyhedral description of Scops", false, 4422 false); 4423 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); 4424 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); 4425 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 4426 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 4427 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 4428 INITIALIZE_PASS_DEPENDENCY(ScopDetection); 4429 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 4430 INITIALIZE_PASS_END(ScopInfo, "polly-scops", 4431 "Polly - Create polyhedral description of Scops", false, 4432 false) 4433