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 auto &Loc = getAccessInstruction() ? getAccessInstruction()->getDebugLoc() 613 : DebugLoc(); 614 Statement->getParent()->addAssumption(INBOUNDS, Outside, Loc, AS_ASSUMPTION); 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 auto *NotExecuted = isl_set_complement(isl_set_params(getDomain())); 1317 for (size_t i = 0; i < Sizes.size(); i++) { 1318 auto *Expr = Subscripts[i + IndexOffset]; 1319 auto Size = Sizes[i]; 1320 1321 InvariantLoadsSetTy AccessILS; 1322 if (!isAffineExpr(&Parent.getRegion(), Expr, SE, nullptr, &AccessILS)) 1323 continue; 1324 1325 bool NonAffine = false; 1326 for (LoadInst *LInst : AccessILS) 1327 if (!ScopRIL.count(LInst)) 1328 NonAffine = true; 1329 1330 if (NonAffine) 1331 continue; 1332 1333 isl_pw_aff *AccessOffset = getPwAff(Expr); 1334 AccessOffset = 1335 isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId()); 1336 1337 isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain( 1338 isl_local_space_copy(LSpace), isl_val_int_from_si(Ctx, Size))); 1339 1340 isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize); 1341 OutOfBound = isl_set_intersect(getDomain(), OutOfBound); 1342 OutOfBound = isl_set_params(OutOfBound); 1343 isl_set *InBound = isl_set_complement(OutOfBound); 1344 1345 // A => B == !A or B 1346 isl_set *InBoundIfExecuted = 1347 isl_set_union(isl_set_copy(NotExecuted), InBound); 1348 1349 InBoundIfExecuted = isl_set_coalesce(InBoundIfExecuted); 1350 Parent.addAssumption(INBOUNDS, InBoundIfExecuted, GEP->getDebugLoc(), 1351 AS_ASSUMPTION); 1352 } 1353 1354 isl_local_space_free(LSpace); 1355 isl_set_free(NotExecuted); 1356 } 1357 1358 void ScopStmt::deriveAssumptions(BasicBlock *Block, ScopDetection &SD) { 1359 for (Instruction &Inst : *Block) 1360 if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst)) 1361 deriveAssumptionsFromGEP(GEP, SD); 1362 } 1363 1364 void ScopStmt::collectSurroundingLoops() { 1365 for (unsigned u = 0, e = isl_set_n_dim(Domain); u < e; u++) { 1366 isl_id *DimId = isl_set_get_dim_id(Domain, isl_dim_set, u); 1367 NestLoops.push_back(static_cast<Loop *>(isl_id_get_user(DimId))); 1368 isl_id_free(DimId); 1369 } 1370 } 1371 1372 ScopStmt::ScopStmt(Scop &parent, Region &R) 1373 : Parent(parent), Domain(nullptr), BB(nullptr), R(&R), Build(nullptr) { 1374 1375 BaseName = getIslCompatibleName("Stmt_", R.getNameStr(), ""); 1376 } 1377 1378 ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb) 1379 : Parent(parent), Domain(nullptr), BB(&bb), R(nullptr), Build(nullptr) { 1380 1381 BaseName = getIslCompatibleName("Stmt_", &bb, ""); 1382 } 1383 1384 void ScopStmt::init(ScopDetection &SD) { 1385 assert(!Domain && "init must be called only once"); 1386 1387 buildDomain(); 1388 collectSurroundingLoops(); 1389 buildAccessRelations(); 1390 1391 if (BB) { 1392 deriveAssumptions(BB, SD); 1393 } else { 1394 for (BasicBlock *Block : R->blocks()) { 1395 deriveAssumptions(Block, SD); 1396 } 1397 } 1398 1399 if (DetectReductions) 1400 checkForReductions(); 1401 } 1402 1403 /// @brief Collect loads which might form a reduction chain with @p StoreMA 1404 /// 1405 /// Check if the stored value for @p StoreMA is a binary operator with one or 1406 /// two loads as operands. If the binary operand is commutative & associative, 1407 /// used only once (by @p StoreMA) and its load operands are also used only 1408 /// once, we have found a possible reduction chain. It starts at an operand 1409 /// load and includes the binary operator and @p StoreMA. 1410 /// 1411 /// Note: We allow only one use to ensure the load and binary operator cannot 1412 /// escape this block or into any other store except @p StoreMA. 1413 void ScopStmt::collectCandiateReductionLoads( 1414 MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) { 1415 auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction()); 1416 if (!Store) 1417 return; 1418 1419 // Skip if there is not one binary operator between the load and the store 1420 auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand()); 1421 if (!BinOp) 1422 return; 1423 1424 // Skip if the binary operators has multiple uses 1425 if (BinOp->getNumUses() != 1) 1426 return; 1427 1428 // Skip if the opcode of the binary operator is not commutative/associative 1429 if (!BinOp->isCommutative() || !BinOp->isAssociative()) 1430 return; 1431 1432 // Skip if the binary operator is outside the current SCoP 1433 if (BinOp->getParent() != Store->getParent()) 1434 return; 1435 1436 // Skip if it is a multiplicative reduction and we disabled them 1437 if (DisableMultiplicativeReductions && 1438 (BinOp->getOpcode() == Instruction::Mul || 1439 BinOp->getOpcode() == Instruction::FMul)) 1440 return; 1441 1442 // Check the binary operator operands for a candidate load 1443 auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0)); 1444 auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1)); 1445 if (!PossibleLoad0 && !PossibleLoad1) 1446 return; 1447 1448 // A load is only a candidate if it cannot escape (thus has only this use) 1449 if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1) 1450 if (PossibleLoad0->getParent() == Store->getParent()) 1451 Loads.push_back(&getArrayAccessFor(PossibleLoad0)); 1452 if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1) 1453 if (PossibleLoad1->getParent() == Store->getParent()) 1454 Loads.push_back(&getArrayAccessFor(PossibleLoad1)); 1455 } 1456 1457 /// @brief Check for reductions in this ScopStmt 1458 /// 1459 /// Iterate over all store memory accesses and check for valid binary reduction 1460 /// like chains. For all candidates we check if they have the same base address 1461 /// and there are no other accesses which overlap with them. The base address 1462 /// check rules out impossible reductions candidates early. The overlap check, 1463 /// together with the "only one user" check in collectCandiateReductionLoads, 1464 /// guarantees that none of the intermediate results will escape during 1465 /// execution of the loop nest. We basically check here that no other memory 1466 /// access can access the same memory as the potential reduction. 1467 void ScopStmt::checkForReductions() { 1468 SmallVector<MemoryAccess *, 2> Loads; 1469 SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates; 1470 1471 // First collect candidate load-store reduction chains by iterating over all 1472 // stores and collecting possible reduction loads. 1473 for (MemoryAccess *StoreMA : MemAccs) { 1474 if (StoreMA->isRead()) 1475 continue; 1476 1477 Loads.clear(); 1478 collectCandiateReductionLoads(StoreMA, Loads); 1479 for (MemoryAccess *LoadMA : Loads) 1480 Candidates.push_back(std::make_pair(LoadMA, StoreMA)); 1481 } 1482 1483 // Then check each possible candidate pair. 1484 for (const auto &CandidatePair : Candidates) { 1485 bool Valid = true; 1486 isl_map *LoadAccs = CandidatePair.first->getAccessRelation(); 1487 isl_map *StoreAccs = CandidatePair.second->getAccessRelation(); 1488 1489 // Skip those with obviously unequal base addresses. 1490 if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) { 1491 isl_map_free(LoadAccs); 1492 isl_map_free(StoreAccs); 1493 continue; 1494 } 1495 1496 // And check if the remaining for overlap with other memory accesses. 1497 isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs); 1498 AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain()); 1499 isl_set *AllAccs = isl_map_range(AllAccsRel); 1500 1501 for (MemoryAccess *MA : MemAccs) { 1502 if (MA == CandidatePair.first || MA == CandidatePair.second) 1503 continue; 1504 1505 isl_map *AccRel = 1506 isl_map_intersect_domain(MA->getAccessRelation(), getDomain()); 1507 isl_set *Accs = isl_map_range(AccRel); 1508 1509 if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) { 1510 isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs)); 1511 Valid = Valid && isl_set_is_empty(OverlapAccs); 1512 isl_set_free(OverlapAccs); 1513 } 1514 } 1515 1516 isl_set_free(AllAccs); 1517 if (!Valid) 1518 continue; 1519 1520 const LoadInst *Load = 1521 dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction()); 1522 MemoryAccess::ReductionType RT = 1523 getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load); 1524 1525 // If no overlapping access was found we mark the load and store as 1526 // reduction like. 1527 CandidatePair.first->markAsReductionLike(RT); 1528 CandidatePair.second->markAsReductionLike(RT); 1529 } 1530 } 1531 1532 std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); } 1533 1534 std::string ScopStmt::getScheduleStr() const { 1535 auto *S = getSchedule(); 1536 auto Str = stringFromIslObj(S); 1537 isl_map_free(S); 1538 return Str; 1539 } 1540 1541 BasicBlock *ScopStmt::getEntryBlock() const { 1542 if (isBlockStmt()) 1543 return getBasicBlock(); 1544 return getRegion()->getEntry(); 1545 } 1546 1547 RegionNode *ScopStmt::getRegionNode() const { 1548 if (isRegionStmt()) 1549 return getRegion()->getNode(); 1550 return getParent()->getRegion().getBBNode(getBasicBlock()); 1551 } 1552 1553 unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); } 1554 1555 unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); } 1556 1557 const char *ScopStmt::getBaseName() const { return BaseName.c_str(); } 1558 1559 const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const { 1560 return NestLoops[Dimension]; 1561 } 1562 1563 isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); } 1564 1565 __isl_give isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); } 1566 1567 __isl_give isl_space *ScopStmt::getDomainSpace() const { 1568 return isl_set_get_space(Domain); 1569 } 1570 1571 __isl_give isl_id *ScopStmt::getDomainId() const { 1572 return isl_set_get_tuple_id(Domain); 1573 } 1574 1575 ScopStmt::~ScopStmt() { isl_set_free(Domain); } 1576 1577 void ScopStmt::print(raw_ostream &OS) const { 1578 OS << "\t" << getBaseName() << "\n"; 1579 OS.indent(12) << "Domain :=\n"; 1580 1581 if (Domain) { 1582 OS.indent(16) << getDomainStr() << ";\n"; 1583 } else 1584 OS.indent(16) << "n/a\n"; 1585 1586 OS.indent(12) << "Schedule :=\n"; 1587 1588 if (Domain) { 1589 OS.indent(16) << getScheduleStr() << ";\n"; 1590 } else 1591 OS.indent(16) << "n/a\n"; 1592 1593 for (MemoryAccess *Access : MemAccs) 1594 Access->print(OS); 1595 } 1596 1597 void ScopStmt::dump() const { print(dbgs()); } 1598 1599 void ScopStmt::removeMemoryAccesses(MemoryAccessList &InvMAs) { 1600 // Remove all memory accesses in @p InvMAs from this statement 1601 // together with all scalar accesses that were caused by them. 1602 // MK_Value READs have no access instruction, hence would not be removed by 1603 // this function. However, it is only used for invariant LoadInst accesses, 1604 // its arguments are always affine, hence synthesizable, and therefore there 1605 // are no MK_Value READ accesses to be removed. 1606 for (MemoryAccess *MA : InvMAs) { 1607 auto Predicate = [&](MemoryAccess *Acc) { 1608 return Acc->getAccessInstruction() == MA->getAccessInstruction(); 1609 }; 1610 MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate), 1611 MemAccs.end()); 1612 InstructionToAccess.erase(MA->getAccessInstruction()); 1613 } 1614 } 1615 1616 //===----------------------------------------------------------------------===// 1617 /// Scop class implement 1618 1619 void Scop::setContext(__isl_take isl_set *NewContext) { 1620 NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context)); 1621 isl_set_free(Context); 1622 Context = NewContext; 1623 } 1624 1625 /// @brief Remap parameter values but keep AddRecs valid wrt. invariant loads. 1626 struct SCEVSensitiveParameterRewriter 1627 : public SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *> { 1628 ValueToValueMap &VMap; 1629 ScalarEvolution &SE; 1630 1631 public: 1632 SCEVSensitiveParameterRewriter(ValueToValueMap &VMap, ScalarEvolution &SE) 1633 : VMap(VMap), SE(SE) {} 1634 1635 static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE, 1636 ValueToValueMap &VMap) { 1637 SCEVSensitiveParameterRewriter SSPR(VMap, SE); 1638 return SSPR.visit(E); 1639 } 1640 1641 const SCEV *visit(const SCEV *E) { 1642 return SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *>::visit(E); 1643 } 1644 1645 const SCEV *visitConstant(const SCEVConstant *E) { return E; } 1646 1647 const SCEV *visitTruncateExpr(const SCEVTruncateExpr *E) { 1648 return SE.getTruncateExpr(visit(E->getOperand()), E->getType()); 1649 } 1650 1651 const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *E) { 1652 return SE.getZeroExtendExpr(visit(E->getOperand()), E->getType()); 1653 } 1654 1655 const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *E) { 1656 return SE.getSignExtendExpr(visit(E->getOperand()), E->getType()); 1657 } 1658 1659 const SCEV *visitAddExpr(const SCEVAddExpr *E) { 1660 SmallVector<const SCEV *, 4> Operands; 1661 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1662 Operands.push_back(visit(E->getOperand(i))); 1663 return SE.getAddExpr(Operands); 1664 } 1665 1666 const SCEV *visitMulExpr(const SCEVMulExpr *E) { 1667 SmallVector<const SCEV *, 4> Operands; 1668 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1669 Operands.push_back(visit(E->getOperand(i))); 1670 return SE.getMulExpr(Operands); 1671 } 1672 1673 const SCEV *visitSMaxExpr(const SCEVSMaxExpr *E) { 1674 SmallVector<const SCEV *, 4> Operands; 1675 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1676 Operands.push_back(visit(E->getOperand(i))); 1677 return SE.getSMaxExpr(Operands); 1678 } 1679 1680 const SCEV *visitUMaxExpr(const SCEVUMaxExpr *E) { 1681 SmallVector<const SCEV *, 4> Operands; 1682 for (int i = 0, e = E->getNumOperands(); i < e; ++i) 1683 Operands.push_back(visit(E->getOperand(i))); 1684 return SE.getUMaxExpr(Operands); 1685 } 1686 1687 const SCEV *visitUDivExpr(const SCEVUDivExpr *E) { 1688 return SE.getUDivExpr(visit(E->getLHS()), visit(E->getRHS())); 1689 } 1690 1691 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) { 1692 auto *Start = visit(E->getStart()); 1693 auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0), 1694 visit(E->getStepRecurrence(SE)), 1695 E->getLoop(), SCEV::FlagAnyWrap); 1696 return SE.getAddExpr(Start, AddRec); 1697 } 1698 1699 const SCEV *visitUnknown(const SCEVUnknown *E) { 1700 if (auto *NewValue = VMap.lookup(E->getValue())) 1701 return SE.getUnknown(NewValue); 1702 return E; 1703 } 1704 }; 1705 1706 const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *S) { 1707 return SCEVSensitiveParameterRewriter::rewrite(S, *SE, InvEquivClassVMap); 1708 } 1709 1710 void Scop::addParams(std::vector<const SCEV *> NewParameters) { 1711 for (const SCEV *Parameter : NewParameters) { 1712 Parameter = extractConstantFactor(Parameter, *SE).second; 1713 1714 // Normalize the SCEV to get the representing element for an invariant load. 1715 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1716 1717 if (ParameterIds.find(Parameter) != ParameterIds.end()) 1718 continue; 1719 1720 int dimension = Parameters.size(); 1721 1722 Parameters.push_back(Parameter); 1723 ParameterIds[Parameter] = dimension; 1724 } 1725 } 1726 1727 __isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) { 1728 // Normalize the SCEV to get the representing element for an invariant load. 1729 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1730 1731 ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter); 1732 1733 if (IdIter == ParameterIds.end()) 1734 return nullptr; 1735 1736 std::string ParameterName; 1737 1738 ParameterName = "p_" + utostr(IdIter->second); 1739 1740 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) { 1741 Value *Val = ValueParameter->getValue(); 1742 1743 // If this parameter references a specific Value and this value has a name 1744 // we use this name as it is likely to be unique and more useful than just 1745 // a number. 1746 if (Val->hasName()) 1747 ParameterName = Val->getName(); 1748 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) { 1749 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets(); 1750 if (LoadOrigin->hasName()) { 1751 ParameterName += "_loaded_from_"; 1752 ParameterName += 1753 LI->getPointerOperand()->stripInBoundsOffsets()->getName(); 1754 } 1755 } 1756 } 1757 1758 return isl_id_alloc(getIslCtx(), ParameterName.c_str(), 1759 const_cast<void *>((const void *)Parameter)); 1760 } 1761 1762 isl_set *Scop::addNonEmptyDomainConstraints(isl_set *C) const { 1763 isl_set *DomainContext = isl_union_set_params(getDomains()); 1764 return isl_set_intersect_params(C, DomainContext); 1765 } 1766 1767 void Scop::addWrappingContext() { 1768 if (IgnoreIntegerWrapping) 1769 return; 1770 1771 auto *WrappingContext = Affinator.getWrappingContext(); 1772 addAssumption(WRAPPING, WrappingContext, DebugLoc(), AS_RESTRICTION); 1773 } 1774 1775 void Scop::addUserAssumptions(AssumptionCache &AC, DominatorTree &DT, 1776 LoopInfo &LI) { 1777 auto *R = &getRegion(); 1778 auto &F = *R->getEntry()->getParent(); 1779 for (auto &Assumption : AC.assumptions()) { 1780 auto *CI = dyn_cast_or_null<CallInst>(Assumption); 1781 if (!CI || CI->getNumArgOperands() != 1) 1782 continue; 1783 if (!DT.dominates(CI->getParent(), R->getEntry())) 1784 continue; 1785 1786 auto *Val = CI->getArgOperand(0); 1787 std::vector<const SCEV *> Params; 1788 if (!isAffineParamConstraint(Val, R, *SE, Params)) { 1789 emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, 1790 CI->getDebugLoc(), 1791 "Non-affine user assumption ignored."); 1792 continue; 1793 } 1794 1795 addParams(Params); 1796 1797 auto *L = LI.getLoopFor(CI->getParent()); 1798 SmallVector<isl_set *, 2> ConditionSets; 1799 buildConditionSets(*this, Val, nullptr, L, Context, ConditionSets); 1800 assert(ConditionSets.size() == 2); 1801 isl_set_free(ConditionSets[1]); 1802 1803 auto *AssumptionCtx = ConditionSets[0]; 1804 emitOptimizationRemarkAnalysis( 1805 F.getContext(), DEBUG_TYPE, F, CI->getDebugLoc(), 1806 "Use user assumption: " + stringFromIslObj(AssumptionCtx)); 1807 Context = isl_set_intersect(Context, AssumptionCtx); 1808 } 1809 } 1810 1811 void Scop::addUserContext() { 1812 if (UserContextStr.empty()) 1813 return; 1814 1815 isl_set *UserContext = 1816 isl_set_read_from_str(getIslCtx(), UserContextStr.c_str()); 1817 isl_space *Space = getParamSpace(); 1818 if (isl_space_dim(Space, isl_dim_param) != 1819 isl_set_dim(UserContext, isl_dim_param)) { 1820 auto SpaceStr = isl_space_to_str(Space); 1821 errs() << "Error: the context provided in -polly-context has not the same " 1822 << "number of dimensions than the computed context. Due to this " 1823 << "mismatch, the -polly-context option is ignored. Please provide " 1824 << "the context in the parameter space: " << SpaceStr << ".\n"; 1825 free(SpaceStr); 1826 isl_set_free(UserContext); 1827 isl_space_free(Space); 1828 return; 1829 } 1830 1831 for (unsigned i = 0; i < isl_space_dim(Space, isl_dim_param); i++) { 1832 auto *NameContext = isl_set_get_dim_name(Context, isl_dim_param, i); 1833 auto *NameUserContext = isl_set_get_dim_name(UserContext, isl_dim_param, i); 1834 1835 if (strcmp(NameContext, NameUserContext) != 0) { 1836 auto SpaceStr = isl_space_to_str(Space); 1837 errs() << "Error: the name of dimension " << i 1838 << " provided in -polly-context " 1839 << "is '" << NameUserContext << "', but the name in the computed " 1840 << "context is '" << NameContext 1841 << "'. Due to this name mismatch, " 1842 << "the -polly-context option is ignored. Please provide " 1843 << "the context in the parameter space: " << SpaceStr << ".\n"; 1844 free(SpaceStr); 1845 isl_set_free(UserContext); 1846 isl_space_free(Space); 1847 return; 1848 } 1849 1850 UserContext = 1851 isl_set_set_dim_id(UserContext, isl_dim_param, i, 1852 isl_space_get_dim_id(Space, isl_dim_param, i)); 1853 } 1854 1855 Context = isl_set_intersect(Context, UserContext); 1856 isl_space_free(Space); 1857 } 1858 1859 void Scop::buildInvariantEquivalenceClasses(ScopDetection &SD) { 1860 DenseMap<std::pair<const SCEV *, Type *>, LoadInst *> EquivClasses; 1861 1862 const InvariantLoadsSetTy &RIL = *SD.getRequiredInvariantLoads(&getRegion()); 1863 for (LoadInst *LInst : RIL) { 1864 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 1865 1866 Type *Ty = LInst->getType(); 1867 LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)]; 1868 if (ClassRep) { 1869 InvEquivClassVMap[LInst] = ClassRep; 1870 continue; 1871 } 1872 1873 ClassRep = LInst; 1874 InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList(), nullptr, 1875 Ty); 1876 } 1877 } 1878 1879 void Scop::buildContext() { 1880 isl_space *Space = isl_space_params_alloc(getIslCtx(), 0); 1881 Context = isl_set_universe(isl_space_copy(Space)); 1882 InvalidContext = isl_set_empty(isl_space_copy(Space)); 1883 AssumedContext = isl_set_universe(Space); 1884 } 1885 1886 void Scop::addParameterBounds() { 1887 for (const auto &ParamID : ParameterIds) { 1888 int dim = ParamID.second; 1889 1890 ConstantRange SRange = SE->getSignedRange(ParamID.first); 1891 1892 Context = addRangeBoundsToSet(Context, SRange, dim, isl_dim_param); 1893 } 1894 } 1895 1896 void Scop::realignParams() { 1897 // Add all parameters into a common model. 1898 isl_space *Space = isl_space_params_alloc(getIslCtx(), ParameterIds.size()); 1899 1900 for (const auto &ParamID : ParameterIds) { 1901 const SCEV *Parameter = ParamID.first; 1902 isl_id *id = getIdForParam(Parameter); 1903 Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id); 1904 } 1905 1906 // Align the parameters of all data structures to the model. 1907 Context = isl_set_align_params(Context, Space); 1908 1909 for (ScopStmt &Stmt : *this) 1910 Stmt.realignParams(); 1911 } 1912 1913 static __isl_give isl_set * 1914 simplifyAssumptionContext(__isl_take isl_set *AssumptionContext, 1915 const Scop &S) { 1916 // If we modelt all blocks in the SCoP that have side effects we can simplify 1917 // the context with the constraints that are needed for anything to be 1918 // executed at all. However, if we have error blocks in the SCoP we already 1919 // assumed some parameter combinations cannot occure and removed them from the 1920 // domains, thus we cannot use the remaining domain to simplify the 1921 // assumptions. 1922 if (!S.hasErrorBlock()) { 1923 isl_set *DomainParameters = isl_union_set_params(S.getDomains()); 1924 AssumptionContext = 1925 isl_set_gist_params(AssumptionContext, DomainParameters); 1926 } 1927 1928 AssumptionContext = isl_set_gist_params(AssumptionContext, S.getContext()); 1929 return AssumptionContext; 1930 } 1931 1932 void Scop::simplifyContexts() { 1933 // The parameter constraints of the iteration domains give us a set of 1934 // constraints that need to hold for all cases where at least a single 1935 // statement iteration is executed in the whole scop. We now simplify the 1936 // assumed context under the assumption that such constraints hold and at 1937 // least a single statement iteration is executed. For cases where no 1938 // statement instances are executed, the assumptions we have taken about 1939 // the executed code do not matter and can be changed. 1940 // 1941 // WARNING: This only holds if the assumptions we have taken do not reduce 1942 // the set of statement instances that are executed. Otherwise we 1943 // may run into a case where the iteration domains suggest that 1944 // for a certain set of parameter constraints no code is executed, 1945 // but in the original program some computation would have been 1946 // performed. In such a case, modifying the run-time conditions and 1947 // possibly influencing the run-time check may cause certain scops 1948 // to not be executed. 1949 // 1950 // Example: 1951 // 1952 // When delinearizing the following code: 1953 // 1954 // for (long i = 0; i < 100; i++) 1955 // for (long j = 0; j < m; j++) 1956 // A[i+p][j] = 1.0; 1957 // 1958 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as 1959 // otherwise we would access out of bound data. Now, knowing that code is 1960 // only executed for the case m >= 0, it is sufficient to assume p >= 0. 1961 AssumedContext = simplifyAssumptionContext(AssumedContext, *this); 1962 InvalidContext = isl_set_align_params(InvalidContext, getParamSpace()); 1963 } 1964 1965 /// @brief Add the minimal/maximal access in @p Set to @p User. 1966 static isl_stat buildMinMaxAccess(__isl_take isl_set *Set, void *User) { 1967 Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User; 1968 isl_pw_multi_aff *MinPMA, *MaxPMA; 1969 isl_pw_aff *LastDimAff; 1970 isl_aff *OneAff; 1971 unsigned Pos; 1972 1973 // Restrict the number of parameters involved in the access as the lexmin/ 1974 // lexmax computation will take too long if this number is high. 1975 // 1976 // Experiments with a simple test case using an i7 4800MQ: 1977 // 1978 // #Parameters involved | Time (in sec) 1979 // 6 | 0.01 1980 // 7 | 0.04 1981 // 8 | 0.12 1982 // 9 | 0.40 1983 // 10 | 1.54 1984 // 11 | 6.78 1985 // 12 | 30.38 1986 // 1987 if (isl_set_n_param(Set) > RunTimeChecksMaxParameters) { 1988 unsigned InvolvedParams = 0; 1989 for (unsigned u = 0, e = isl_set_n_param(Set); u < e; u++) 1990 if (isl_set_involves_dims(Set, isl_dim_param, u, 1)) 1991 InvolvedParams++; 1992 1993 if (InvolvedParams > RunTimeChecksMaxParameters) { 1994 isl_set_free(Set); 1995 return isl_stat_error; 1996 } 1997 } 1998 1999 Set = isl_set_remove_divs(Set); 2000 2001 MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set)); 2002 MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set)); 2003 2004 MinPMA = isl_pw_multi_aff_coalesce(MinPMA); 2005 MaxPMA = isl_pw_multi_aff_coalesce(MaxPMA); 2006 2007 // Adjust the last dimension of the maximal access by one as we want to 2008 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer 2009 // we test during code generation might now point after the end of the 2010 // allocated array but we will never dereference it anyway. 2011 assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) && 2012 "Assumed at least one output dimension"); 2013 Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1; 2014 LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos); 2015 OneAff = isl_aff_zero_on_domain( 2016 isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff))); 2017 OneAff = isl_aff_add_constant_si(OneAff, 1); 2018 LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff)); 2019 MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff); 2020 2021 MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA)); 2022 2023 isl_set_free(Set); 2024 return isl_stat_ok; 2025 } 2026 2027 static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) { 2028 isl_set *Domain = MA->getStatement()->getDomain(); 2029 Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain)); 2030 return isl_set_reset_tuple_id(Domain); 2031 } 2032 2033 /// @brief Wrapper function to calculate minimal/maximal accesses to each array. 2034 static bool calculateMinMaxAccess(__isl_take isl_union_map *Accesses, 2035 __isl_take isl_union_set *Domains, 2036 Scop::MinMaxVectorTy &MinMaxAccesses) { 2037 2038 Accesses = isl_union_map_intersect_domain(Accesses, Domains); 2039 isl_union_set *Locations = isl_union_map_range(Accesses); 2040 Locations = isl_union_set_coalesce(Locations); 2041 Locations = isl_union_set_detect_equalities(Locations); 2042 bool Valid = (0 == isl_union_set_foreach_set(Locations, buildMinMaxAccess, 2043 &MinMaxAccesses)); 2044 isl_union_set_free(Locations); 2045 return Valid; 2046 } 2047 2048 /// @brief Helper to treat non-affine regions and basic blocks the same. 2049 /// 2050 ///{ 2051 2052 /// @brief Return the block that is the representing block for @p RN. 2053 static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) { 2054 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry() 2055 : RN->getNodeAs<BasicBlock>(); 2056 } 2057 2058 /// @brief Return the @p idx'th block that is executed after @p RN. 2059 static inline BasicBlock * 2060 getRegionNodeSuccessor(RegionNode *RN, TerminatorInst *TI, unsigned idx) { 2061 if (RN->isSubRegion()) { 2062 assert(idx == 0); 2063 return RN->getNodeAs<Region>()->getExit(); 2064 } 2065 return TI->getSuccessor(idx); 2066 } 2067 2068 /// @brief Return the smallest loop surrounding @p RN. 2069 static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) { 2070 if (!RN->isSubRegion()) 2071 return LI.getLoopFor(RN->getNodeAs<BasicBlock>()); 2072 2073 Region *NonAffineSubRegion = RN->getNodeAs<Region>(); 2074 Loop *L = LI.getLoopFor(NonAffineSubRegion->getEntry()); 2075 while (L && NonAffineSubRegion->contains(L)) 2076 L = L->getParentLoop(); 2077 return L; 2078 } 2079 2080 static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) { 2081 if (!RN->isSubRegion()) 2082 return 1; 2083 2084 Region *R = RN->getNodeAs<Region>(); 2085 return std::distance(R->block_begin(), R->block_end()); 2086 } 2087 2088 static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI, 2089 const DominatorTree &DT) { 2090 if (!RN->isSubRegion()) 2091 return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT); 2092 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks()) 2093 if (isErrorBlock(*BB, R, LI, DT)) 2094 return true; 2095 return false; 2096 } 2097 2098 ///} 2099 2100 static inline __isl_give isl_set *addDomainDimId(__isl_take isl_set *Domain, 2101 unsigned Dim, Loop *L) { 2102 Domain = isl_set_lower_bound_si(Domain, isl_dim_set, Dim, -1); 2103 isl_id *DimId = 2104 isl_id_alloc(isl_set_get_ctx(Domain), nullptr, static_cast<void *>(L)); 2105 return isl_set_set_dim_id(Domain, isl_dim_set, Dim, DimId); 2106 } 2107 2108 isl_set *Scop::getDomainConditions(ScopStmt *Stmt) { 2109 return getDomainConditions(Stmt->getEntryBlock()); 2110 } 2111 2112 isl_set *Scop::getDomainConditions(BasicBlock *BB) { 2113 assert(DomainMap.count(BB) && "Requested BB did not have a domain"); 2114 return isl_set_copy(DomainMap[BB]); 2115 } 2116 2117 void Scop::removeErrorBlockDomains(ScopDetection &SD, DominatorTree &DT, 2118 LoopInfo &LI) { 2119 auto removeDomains = [this, &DT](BasicBlock *Start) { 2120 auto *BBNode = DT.getNode(Start); 2121 for (auto *ErrorChild : depth_first(BBNode)) { 2122 auto *ErrorChildBlock = ErrorChild->getBlock(); 2123 auto *CurrentDomain = DomainMap[ErrorChildBlock]; 2124 auto *Empty = isl_set_empty(isl_set_get_space(CurrentDomain)); 2125 DomainMap[ErrorChildBlock] = Empty; 2126 isl_set_free(CurrentDomain); 2127 } 2128 }; 2129 2130 SmallVector<Region *, 4> Todo = {&R}; 2131 2132 while (!Todo.empty()) { 2133 auto *SubRegion = Todo.back(); 2134 Todo.pop_back(); 2135 2136 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) { 2137 for (auto &Child : *SubRegion) 2138 Todo.push_back(Child.get()); 2139 continue; 2140 } 2141 if (containsErrorBlock(SubRegion->getNode(), getRegion(), LI, DT)) 2142 removeDomains(SubRegion->getEntry()); 2143 } 2144 2145 for (auto *BB : R.blocks()) 2146 if (isErrorBlock(*BB, R, LI, DT)) 2147 removeDomains(BB); 2148 } 2149 2150 void Scop::buildDomains(Region *R, ScopDetection &SD, DominatorTree &DT, 2151 LoopInfo &LI) { 2152 2153 bool IsOnlyNonAffineRegion = SD.isNonAffineSubRegion(R, R); 2154 auto *EntryBB = R->getEntry(); 2155 auto *L = IsOnlyNonAffineRegion ? nullptr : LI.getLoopFor(EntryBB); 2156 int LD = getRelativeLoopDepth(L); 2157 auto *S = isl_set_universe(isl_space_set_alloc(getIslCtx(), 0, LD + 1)); 2158 2159 while (LD-- >= 0) { 2160 S = addDomainDimId(S, LD + 1, L); 2161 L = L->getParentLoop(); 2162 } 2163 2164 DomainMap[EntryBB] = S; 2165 2166 if (IsOnlyNonAffineRegion) 2167 return; 2168 2169 buildDomainsWithBranchConstraints(R, SD, DT, LI); 2170 propagateDomainConstraints(R, SD, DT, LI); 2171 2172 // Error blocks and blocks dominated by them have been assumed to never be 2173 // executed. Representing them in the Scop does not add any value. In fact, 2174 // it is likely to cause issues during construction of the ScopStmts. The 2175 // contents of error blocks have not been verfied to be expressible and 2176 // will cause problems when building up a ScopStmt for them. 2177 // Furthermore, basic blocks dominated by error blocks may reference 2178 // instructions in the error block which, if the error block is not modeled, 2179 // can themselves not be constructed properly. 2180 removeErrorBlockDomains(SD, DT, LI); 2181 } 2182 2183 void Scop::buildDomainsWithBranchConstraints(Region *R, ScopDetection &SD, 2184 DominatorTree &DT, LoopInfo &LI) { 2185 auto &BoxedLoops = *SD.getBoxedLoops(&getRegion()); 2186 2187 // To create the domain for each block in R we iterate over all blocks and 2188 // subregions in R and propagate the conditions under which the current region 2189 // element is executed. To this end we iterate in reverse post order over R as 2190 // it ensures that we first visit all predecessors of a region node (either a 2191 // basic block or a subregion) before we visit the region node itself. 2192 // Initially, only the domain for the SCoP region entry block is set and from 2193 // there we propagate the current domain to all successors, however we add the 2194 // condition that the successor is actually executed next. 2195 // As we are only interested in non-loop carried constraints here we can 2196 // simply skip loop back edges. 2197 2198 ReversePostOrderTraversal<Region *> RTraversal(R); 2199 for (auto *RN : RTraversal) { 2200 2201 // Recurse for affine subregions but go on for basic blocks and non-affine 2202 // subregions. 2203 if (RN->isSubRegion()) { 2204 Region *SubRegion = RN->getNodeAs<Region>(); 2205 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) { 2206 buildDomainsWithBranchConstraints(SubRegion, SD, DT, LI); 2207 continue; 2208 } 2209 } 2210 2211 if (containsErrorBlock(RN, getRegion(), LI, DT)) 2212 HasErrorBlock = true; 2213 2214 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2215 TerminatorInst *TI = BB->getTerminator(); 2216 2217 if (isa<UnreachableInst>(TI)) 2218 continue; 2219 2220 isl_set *Domain = DomainMap.lookup(BB); 2221 if (!Domain) 2222 continue; 2223 2224 Loop *BBLoop = getRegionNodeLoop(RN, LI); 2225 int BBLoopDepth = getRelativeLoopDepth(BBLoop); 2226 2227 // Build the condition sets for the successor nodes of the current region 2228 // node. If it is a non-affine subregion we will always execute the single 2229 // exit node, hence the single entry node domain is the condition set. For 2230 // basic blocks we use the helper function buildConditionSets. 2231 SmallVector<isl_set *, 8> ConditionSets; 2232 if (RN->isSubRegion()) 2233 ConditionSets.push_back(isl_set_copy(Domain)); 2234 else 2235 buildConditionSets(*this, TI, BBLoop, Domain, ConditionSets); 2236 2237 // Now iterate over the successors and set their initial domain based on 2238 // their condition set. We skip back edges here and have to be careful when 2239 // we leave a loop not to keep constraints over a dimension that doesn't 2240 // exist anymore. 2241 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size()); 2242 for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) { 2243 isl_set *CondSet = ConditionSets[u]; 2244 BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u); 2245 2246 // Skip back edges. 2247 if (DT.dominates(SuccBB, BB)) { 2248 isl_set_free(CondSet); 2249 continue; 2250 } 2251 2252 // Do not adjust the number of dimensions if we enter a boxed loop or are 2253 // in a non-affine subregion or if the surrounding loop stays the same. 2254 Loop *SuccBBLoop = LI.getLoopFor(SuccBB); 2255 while (BoxedLoops.count(SuccBBLoop)) 2256 SuccBBLoop = SuccBBLoop->getParentLoop(); 2257 2258 if (BBLoop != SuccBBLoop) { 2259 2260 // Check if the edge to SuccBB is a loop entry or exit edge. If so 2261 // adjust the dimensionality accordingly. Lastly, if we leave a loop 2262 // and enter a new one we need to drop the old constraints. 2263 int SuccBBLoopDepth = getRelativeLoopDepth(SuccBBLoop); 2264 unsigned LoopDepthDiff = std::abs(BBLoopDepth - SuccBBLoopDepth); 2265 if (BBLoopDepth > SuccBBLoopDepth) { 2266 CondSet = isl_set_project_out(CondSet, isl_dim_set, 2267 isl_set_n_dim(CondSet) - LoopDepthDiff, 2268 LoopDepthDiff); 2269 } else if (SuccBBLoopDepth > BBLoopDepth) { 2270 assert(LoopDepthDiff == 1); 2271 CondSet = isl_set_add_dims(CondSet, isl_dim_set, 1); 2272 CondSet = addDomainDimId(CondSet, SuccBBLoopDepth, SuccBBLoop); 2273 } else if (BBLoopDepth >= 0) { 2274 assert(LoopDepthDiff <= 1); 2275 CondSet = isl_set_project_out(CondSet, isl_dim_set, BBLoopDepth, 1); 2276 CondSet = isl_set_add_dims(CondSet, isl_dim_set, 1); 2277 CondSet = addDomainDimId(CondSet, SuccBBLoopDepth, SuccBBLoop); 2278 } 2279 } 2280 2281 // Set the domain for the successor or merge it with an existing domain in 2282 // case there are multiple paths (without loop back edges) to the 2283 // successor block. 2284 isl_set *&SuccDomain = DomainMap[SuccBB]; 2285 if (!SuccDomain) 2286 SuccDomain = CondSet; 2287 else 2288 SuccDomain = isl_set_union(SuccDomain, CondSet); 2289 2290 SuccDomain = isl_set_coalesce(SuccDomain); 2291 if (isl_set_n_basic_set(SuccDomain) > MaxConjunctsInDomain) { 2292 auto *Empty = isl_set_empty(isl_set_get_space(SuccDomain)); 2293 isl_set_free(SuccDomain); 2294 SuccDomain = Empty; 2295 invalidate(ERROR_DOMAINCONJUNCTS, DebugLoc()); 2296 } 2297 } 2298 } 2299 } 2300 2301 /// @brief Return the domain for @p BB wrt @p DomainMap. 2302 /// 2303 /// This helper function will lookup @p BB in @p DomainMap but also handle the 2304 /// case where @p BB is contained in a non-affine subregion using the region 2305 /// tree obtained by @p RI. 2306 static __isl_give isl_set * 2307 getDomainForBlock(BasicBlock *BB, DenseMap<BasicBlock *, isl_set *> &DomainMap, 2308 RegionInfo &RI) { 2309 auto DIt = DomainMap.find(BB); 2310 if (DIt != DomainMap.end()) 2311 return isl_set_copy(DIt->getSecond()); 2312 2313 Region *R = RI.getRegionFor(BB); 2314 while (R->getEntry() == BB) 2315 R = R->getParent(); 2316 return getDomainForBlock(R->getEntry(), DomainMap, RI); 2317 } 2318 2319 void Scop::propagateDomainConstraints(Region *R, ScopDetection &SD, 2320 DominatorTree &DT, LoopInfo &LI) { 2321 // Iterate over the region R and propagate the domain constrains from the 2322 // predecessors to the current node. In contrast to the 2323 // buildDomainsWithBranchConstraints function, this one will pull the domain 2324 // information from the predecessors instead of pushing it to the successors. 2325 // Additionally, we assume the domains to be already present in the domain 2326 // map here. However, we iterate again in reverse post order so we know all 2327 // predecessors have been visited before a block or non-affine subregion is 2328 // visited. 2329 2330 // The set of boxed loops (loops in non-affine subregions) for this SCoP. 2331 auto &BoxedLoops = *SD.getBoxedLoops(&getRegion()); 2332 2333 ReversePostOrderTraversal<Region *> RTraversal(R); 2334 for (auto *RN : RTraversal) { 2335 2336 // Recurse for affine subregions but go on for basic blocks and non-affine 2337 // subregions. 2338 if (RN->isSubRegion()) { 2339 Region *SubRegion = RN->getNodeAs<Region>(); 2340 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) { 2341 propagateDomainConstraints(SubRegion, SD, DT, LI); 2342 continue; 2343 } 2344 } 2345 2346 // Get the domain for the current block and check if it was initialized or 2347 // not. The only way it was not is if this block is only reachable via error 2348 // blocks, thus will not be executed under the assumptions we make. Such 2349 // blocks have to be skipped as their predecessors might not have domains 2350 // either. It would not benefit us to compute the domain anyway, only the 2351 // domains of the error blocks that are reachable from non-error blocks 2352 // are needed to generate assumptions. 2353 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2354 isl_set *&Domain = DomainMap[BB]; 2355 if (!Domain) { 2356 DomainMap.erase(BB); 2357 continue; 2358 } 2359 2360 Loop *BBLoop = getRegionNodeLoop(RN, LI); 2361 int BBLoopDepth = getRelativeLoopDepth(BBLoop); 2362 2363 isl_set *PredDom = isl_set_empty(isl_set_get_space(Domain)); 2364 for (auto *PredBB : predecessors(BB)) { 2365 2366 // Skip backedges 2367 if (DT.dominates(BB, PredBB)) 2368 continue; 2369 2370 isl_set *PredBBDom = nullptr; 2371 2372 // Handle the SCoP entry block with its outside predecessors. 2373 if (!getRegion().contains(PredBB)) 2374 PredBBDom = isl_set_universe(isl_set_get_space(PredDom)); 2375 2376 if (!PredBBDom) { 2377 // Determine the loop depth of the predecessor and adjust its domain to 2378 // the domain of the current block. This can mean we have to: 2379 // o) Drop a dimension if this block is the exit of a loop, not the 2380 // header of a new loop and the predecessor was part of the loop. 2381 // o) Add an unconstrainted new dimension if this block is the header 2382 // of a loop and the predecessor is not part of it. 2383 // o) Drop the information about the innermost loop dimension when the 2384 // predecessor and the current block are surrounded by different 2385 // loops in the same depth. 2386 PredBBDom = getDomainForBlock(PredBB, DomainMap, *R->getRegionInfo()); 2387 Loop *PredBBLoop = LI.getLoopFor(PredBB); 2388 while (BoxedLoops.count(PredBBLoop)) 2389 PredBBLoop = PredBBLoop->getParentLoop(); 2390 2391 int PredBBLoopDepth = getRelativeLoopDepth(PredBBLoop); 2392 unsigned LoopDepthDiff = std::abs(BBLoopDepth - PredBBLoopDepth); 2393 if (BBLoopDepth < PredBBLoopDepth) 2394 PredBBDom = isl_set_project_out( 2395 PredBBDom, isl_dim_set, isl_set_n_dim(PredBBDom) - LoopDepthDiff, 2396 LoopDepthDiff); 2397 else if (PredBBLoopDepth < BBLoopDepth) { 2398 assert(LoopDepthDiff == 1); 2399 PredBBDom = isl_set_add_dims(PredBBDom, isl_dim_set, 1); 2400 } else if (BBLoop != PredBBLoop && BBLoopDepth >= 0) { 2401 assert(LoopDepthDiff <= 1); 2402 PredBBDom = isl_set_drop_constraints_involving_dims( 2403 PredBBDom, isl_dim_set, BBLoopDepth, 1); 2404 } 2405 } 2406 2407 PredDom = isl_set_union(PredDom, PredBBDom); 2408 } 2409 2410 // Under the union of all predecessor conditions we can reach this block. 2411 Domain = isl_set_coalesce(isl_set_intersect(Domain, PredDom)); 2412 2413 if (BBLoop && BBLoop->getHeader() == BB && getRegion().contains(BBLoop)) 2414 addLoopBoundsToHeaderDomain(BBLoop, LI); 2415 2416 // Add assumptions for error blocks. 2417 if (containsErrorBlock(RN, getRegion(), LI, DT)) { 2418 IsOptimized = true; 2419 isl_set *DomPar = isl_set_params(isl_set_copy(Domain)); 2420 addAssumption(ERRORBLOCK, DomPar, BB->getTerminator()->getDebugLoc(), 2421 AS_RESTRICTION); 2422 } 2423 } 2424 } 2425 2426 /// @brief Create a map from SetSpace -> SetSpace where the dimensions @p Dim 2427 /// is incremented by one and all other dimensions are equal, e.g., 2428 /// [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3] 2429 /// if @p Dim is 2 and @p SetSpace has 4 dimensions. 2430 static __isl_give isl_map * 2431 createNextIterationMap(__isl_take isl_space *SetSpace, unsigned Dim) { 2432 auto *MapSpace = isl_space_map_from_set(SetSpace); 2433 auto *NextIterationMap = isl_map_universe(isl_space_copy(MapSpace)); 2434 for (unsigned u = 0; u < isl_map_n_in(NextIterationMap); u++) 2435 if (u != Dim) 2436 NextIterationMap = 2437 isl_map_equate(NextIterationMap, isl_dim_in, u, isl_dim_out, u); 2438 auto *C = isl_constraint_alloc_equality(isl_local_space_from_space(MapSpace)); 2439 C = isl_constraint_set_constant_si(C, 1); 2440 C = isl_constraint_set_coefficient_si(C, isl_dim_in, Dim, 1); 2441 C = isl_constraint_set_coefficient_si(C, isl_dim_out, Dim, -1); 2442 NextIterationMap = isl_map_add_constraint(NextIterationMap, C); 2443 return NextIterationMap; 2444 } 2445 2446 void Scop::addLoopBoundsToHeaderDomain(Loop *L, LoopInfo &LI) { 2447 int LoopDepth = getRelativeLoopDepth(L); 2448 assert(LoopDepth >= 0 && "Loop in region should have at least depth one"); 2449 2450 BasicBlock *HeaderBB = L->getHeader(); 2451 assert(DomainMap.count(HeaderBB)); 2452 isl_set *&HeaderBBDom = DomainMap[HeaderBB]; 2453 2454 isl_map *NextIterationMap = 2455 createNextIterationMap(isl_set_get_space(HeaderBBDom), LoopDepth); 2456 2457 isl_set *UnionBackedgeCondition = 2458 isl_set_empty(isl_set_get_space(HeaderBBDom)); 2459 2460 SmallVector<llvm::BasicBlock *, 4> LatchBlocks; 2461 L->getLoopLatches(LatchBlocks); 2462 2463 for (BasicBlock *LatchBB : LatchBlocks) { 2464 2465 // If the latch is only reachable via error statements we skip it. 2466 isl_set *LatchBBDom = DomainMap.lookup(LatchBB); 2467 if (!LatchBBDom) 2468 continue; 2469 2470 isl_set *BackedgeCondition = nullptr; 2471 2472 TerminatorInst *TI = LatchBB->getTerminator(); 2473 BranchInst *BI = dyn_cast<BranchInst>(TI); 2474 if (BI && BI->isUnconditional()) 2475 BackedgeCondition = isl_set_copy(LatchBBDom); 2476 else { 2477 SmallVector<isl_set *, 8> ConditionSets; 2478 int idx = BI->getSuccessor(0) != HeaderBB; 2479 buildConditionSets(*this, TI, L, LatchBBDom, ConditionSets); 2480 2481 // Free the non back edge condition set as we do not need it. 2482 isl_set_free(ConditionSets[1 - idx]); 2483 2484 BackedgeCondition = ConditionSets[idx]; 2485 } 2486 2487 int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB)); 2488 assert(LatchLoopDepth >= LoopDepth); 2489 BackedgeCondition = 2490 isl_set_project_out(BackedgeCondition, isl_dim_set, LoopDepth + 1, 2491 LatchLoopDepth - LoopDepth); 2492 UnionBackedgeCondition = 2493 isl_set_union(UnionBackedgeCondition, BackedgeCondition); 2494 } 2495 2496 isl_map *ForwardMap = isl_map_lex_le(isl_set_get_space(HeaderBBDom)); 2497 for (int i = 0; i < LoopDepth; i++) 2498 ForwardMap = isl_map_equate(ForwardMap, isl_dim_in, i, isl_dim_out, i); 2499 2500 isl_set *UnionBackedgeConditionComplement = 2501 isl_set_complement(UnionBackedgeCondition); 2502 UnionBackedgeConditionComplement = isl_set_lower_bound_si( 2503 UnionBackedgeConditionComplement, isl_dim_set, LoopDepth, 0); 2504 UnionBackedgeConditionComplement = 2505 isl_set_apply(UnionBackedgeConditionComplement, ForwardMap); 2506 HeaderBBDom = isl_set_subtract(HeaderBBDom, UnionBackedgeConditionComplement); 2507 HeaderBBDom = isl_set_apply(HeaderBBDom, NextIterationMap); 2508 2509 auto Parts = partitionSetParts(HeaderBBDom, LoopDepth); 2510 HeaderBBDom = Parts.second; 2511 2512 // Check if there is a <nsw> tagged AddRec for this loop and if so do not add 2513 // the bounded assumptions to the context as they are already implied by the 2514 // <nsw> tag. 2515 if (Affinator.hasNSWAddRecForLoop(L)) { 2516 isl_set_free(Parts.first); 2517 return; 2518 } 2519 2520 isl_set *UnboundedCtx = isl_set_params(Parts.first); 2521 addAssumption(INFINITELOOP, UnboundedCtx, 2522 HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION); 2523 } 2524 2525 void Scop::buildAliasChecks(AliasAnalysis &AA) { 2526 if (!PollyUseRuntimeAliasChecks) 2527 return; 2528 2529 if (buildAliasGroups(AA)) 2530 return; 2531 2532 // If a problem occurs while building the alias groups we need to delete 2533 // this SCoP and pretend it wasn't valid in the first place. To this end 2534 // we make the assumed context infeasible. 2535 invalidate(ALIASING, DebugLoc()); 2536 2537 DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << getNameStr() 2538 << " could not be created as the number of parameters involved " 2539 "is too high. The SCoP will be " 2540 "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust " 2541 "the maximal number of parameters but be advised that the " 2542 "compile time might increase exponentially.\n\n"); 2543 } 2544 2545 bool Scop::buildAliasGroups(AliasAnalysis &AA) { 2546 // To create sound alias checks we perform the following steps: 2547 // o) Use the alias analysis and an alias set tracker to build alias sets 2548 // for all memory accesses inside the SCoP. 2549 // o) For each alias set we then map the aliasing pointers back to the 2550 // memory accesses we know, thus obtain groups of memory accesses which 2551 // might alias. 2552 // o) We divide each group based on the domains of the minimal/maximal 2553 // accesses. That means two minimal/maximal accesses are only in a group 2554 // if their access domains intersect, otherwise they are in different 2555 // ones. 2556 // o) We partition each group into read only and non read only accesses. 2557 // o) For each group with more than one base pointer we then compute minimal 2558 // and maximal accesses to each array of a group in read only and non 2559 // read only partitions separately. 2560 using AliasGroupTy = SmallVector<MemoryAccess *, 4>; 2561 2562 AliasSetTracker AST(AA); 2563 2564 DenseMap<Value *, MemoryAccess *> PtrToAcc; 2565 DenseSet<Value *> HasWriteAccess; 2566 for (ScopStmt &Stmt : *this) { 2567 2568 // Skip statements with an empty domain as they will never be executed. 2569 isl_set *StmtDomain = Stmt.getDomain(); 2570 bool StmtDomainEmpty = isl_set_is_empty(StmtDomain); 2571 isl_set_free(StmtDomain); 2572 if (StmtDomainEmpty) 2573 continue; 2574 2575 for (MemoryAccess *MA : Stmt) { 2576 if (MA->isScalarKind()) 2577 continue; 2578 if (!MA->isRead()) 2579 HasWriteAccess.insert(MA->getBaseAddr()); 2580 MemAccInst Acc(MA->getAccessInstruction()); 2581 if (MA->isRead() && isa<MemTransferInst>(Acc)) 2582 PtrToAcc[cast<MemTransferInst>(Acc)->getSource()] = MA; 2583 else 2584 PtrToAcc[Acc.getPointerOperand()] = MA; 2585 AST.add(Acc); 2586 } 2587 } 2588 2589 SmallVector<AliasGroupTy, 4> AliasGroups; 2590 for (AliasSet &AS : AST) { 2591 if (AS.isMustAlias() || AS.isForwardingAliasSet()) 2592 continue; 2593 AliasGroupTy AG; 2594 for (auto &PR : AS) 2595 AG.push_back(PtrToAcc[PR.getValue()]); 2596 if (AG.size() < 2) 2597 continue; 2598 AliasGroups.push_back(std::move(AG)); 2599 } 2600 2601 // Split the alias groups based on their domain. 2602 for (unsigned u = 0; u < AliasGroups.size(); u++) { 2603 AliasGroupTy NewAG; 2604 AliasGroupTy &AG = AliasGroups[u]; 2605 AliasGroupTy::iterator AGI = AG.begin(); 2606 isl_set *AGDomain = getAccessDomain(*AGI); 2607 while (AGI != AG.end()) { 2608 MemoryAccess *MA = *AGI; 2609 isl_set *MADomain = getAccessDomain(MA); 2610 if (isl_set_is_disjoint(AGDomain, MADomain)) { 2611 NewAG.push_back(MA); 2612 AGI = AG.erase(AGI); 2613 isl_set_free(MADomain); 2614 } else { 2615 AGDomain = isl_set_union(AGDomain, MADomain); 2616 AGI++; 2617 } 2618 } 2619 if (NewAG.size() > 1) 2620 AliasGroups.push_back(std::move(NewAG)); 2621 isl_set_free(AGDomain); 2622 } 2623 2624 auto &F = *getRegion().getEntry()->getParent(); 2625 MapVector<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs; 2626 SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues; 2627 for (AliasGroupTy &AG : AliasGroups) { 2628 NonReadOnlyBaseValues.clear(); 2629 ReadOnlyPairs.clear(); 2630 2631 if (AG.size() < 2) { 2632 AG.clear(); 2633 continue; 2634 } 2635 2636 for (auto II = AG.begin(); II != AG.end();) { 2637 emitOptimizationRemarkAnalysis( 2638 F.getContext(), DEBUG_TYPE, F, 2639 (*II)->getAccessInstruction()->getDebugLoc(), 2640 "Possibly aliasing pointer, use restrict keyword."); 2641 2642 Value *BaseAddr = (*II)->getBaseAddr(); 2643 if (HasWriteAccess.count(BaseAddr)) { 2644 NonReadOnlyBaseValues.insert(BaseAddr); 2645 II++; 2646 } else { 2647 ReadOnlyPairs[BaseAddr].insert(*II); 2648 II = AG.erase(II); 2649 } 2650 } 2651 2652 // If we don't have read only pointers check if there are at least two 2653 // non read only pointers, otherwise clear the alias group. 2654 if (ReadOnlyPairs.empty() && NonReadOnlyBaseValues.size() <= 1) { 2655 AG.clear(); 2656 continue; 2657 } 2658 2659 // If we don't have non read only pointers clear the alias group. 2660 if (NonReadOnlyBaseValues.empty()) { 2661 AG.clear(); 2662 continue; 2663 } 2664 2665 // Check if we have non-affine accesses left, if so bail out as we cannot 2666 // generate a good access range yet. 2667 for (auto *MA : AG) 2668 if (!MA->isAffine()) { 2669 invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc()); 2670 return false; 2671 } 2672 for (auto &ReadOnlyPair : ReadOnlyPairs) 2673 for (auto *MA : ReadOnlyPair.second) 2674 if (!MA->isAffine()) { 2675 invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc()); 2676 return false; 2677 } 2678 2679 // Calculate minimal and maximal accesses for non read only accesses. 2680 MinMaxAliasGroups.emplace_back(); 2681 MinMaxVectorPairTy &pair = MinMaxAliasGroups.back(); 2682 MinMaxVectorTy &MinMaxAccessesNonReadOnly = pair.first; 2683 MinMaxVectorTy &MinMaxAccessesReadOnly = pair.second; 2684 MinMaxAccessesNonReadOnly.reserve(AG.size()); 2685 2686 isl_union_map *Accesses = isl_union_map_empty(getParamSpace()); 2687 2688 // AG contains only non read only accesses. 2689 for (MemoryAccess *MA : AG) 2690 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation()); 2691 2692 bool Valid = calculateMinMaxAccess(Accesses, getDomains(), 2693 MinMaxAccessesNonReadOnly); 2694 2695 // Bail out if the number of values we need to compare is too large. 2696 // This is important as the number of comparisions grows quadratically with 2697 // the number of values we need to compare. 2698 if (!Valid || (MinMaxAccessesNonReadOnly.size() + !ReadOnlyPairs.empty() > 2699 RunTimeChecksMaxArraysPerGroup)) 2700 return false; 2701 2702 // Calculate minimal and maximal accesses for read only accesses. 2703 MinMaxAccessesReadOnly.reserve(ReadOnlyPairs.size()); 2704 Accesses = isl_union_map_empty(getParamSpace()); 2705 2706 for (const auto &ReadOnlyPair : ReadOnlyPairs) 2707 for (MemoryAccess *MA : ReadOnlyPair.second) 2708 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation()); 2709 2710 Valid = 2711 calculateMinMaxAccess(Accesses, getDomains(), MinMaxAccessesReadOnly); 2712 2713 if (!Valid) 2714 return false; 2715 } 2716 2717 return true; 2718 } 2719 2720 /// @brief Get the smallest loop that contains @p R but is not in @p R. 2721 static Loop *getLoopSurroundingRegion(Region &R, LoopInfo &LI) { 2722 // Start with the smallest loop containing the entry and expand that 2723 // loop until it contains all blocks in the region. If there is a loop 2724 // containing all blocks in the region check if it is itself contained 2725 // and if so take the parent loop as it will be the smallest containing 2726 // the region but not contained by it. 2727 Loop *L = LI.getLoopFor(R.getEntry()); 2728 while (L) { 2729 bool AllContained = true; 2730 for (auto *BB : R.blocks()) 2731 AllContained &= L->contains(BB); 2732 if (AllContained) 2733 break; 2734 L = L->getParentLoop(); 2735 } 2736 2737 return L ? (R.contains(L) ? L->getParentLoop() : L) : nullptr; 2738 } 2739 2740 static unsigned getMaxLoopDepthInRegion(const Region &R, LoopInfo &LI, 2741 ScopDetection &SD) { 2742 2743 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD.getBoxedLoops(&R); 2744 2745 unsigned MinLD = INT_MAX, MaxLD = 0; 2746 for (BasicBlock *BB : R.blocks()) { 2747 if (Loop *L = LI.getLoopFor(BB)) { 2748 if (!R.contains(L)) 2749 continue; 2750 if (BoxedLoops && BoxedLoops->count(L)) 2751 continue; 2752 unsigned LD = L->getLoopDepth(); 2753 MinLD = std::min(MinLD, LD); 2754 MaxLD = std::max(MaxLD, LD); 2755 } 2756 } 2757 2758 // Handle the case that there is no loop in the SCoP first. 2759 if (MaxLD == 0) 2760 return 1; 2761 2762 assert(MinLD >= 1 && "Minimal loop depth should be at least one"); 2763 assert(MaxLD >= MinLD && 2764 "Maximal loop depth was smaller than mininaml loop depth?"); 2765 return MaxLD - MinLD + 1; 2766 } 2767 2768 Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, unsigned MaxLoopDepth) 2769 : SE(&ScalarEvolution), R(R), IsOptimized(false), 2770 HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false), 2771 MaxLoopDepth(MaxLoopDepth), IslCtx(isl_ctx_alloc(), isl_ctx_free), 2772 Context(nullptr), Affinator(this), AssumedContext(nullptr), 2773 InvalidContext(nullptr), Schedule(nullptr) { 2774 isl_options_set_on_error(getIslCtx(), ISL_ON_ERROR_ABORT); 2775 buildContext(); 2776 } 2777 2778 void Scop::init(AliasAnalysis &AA, AssumptionCache &AC, ScopDetection &SD, 2779 DominatorTree &DT, LoopInfo &LI) { 2780 addUserAssumptions(AC, DT, LI); 2781 buildInvariantEquivalenceClasses(SD); 2782 2783 buildDomains(&R, SD, DT, LI); 2784 2785 // Remove empty and ignored statements. 2786 // Exit early in case there are no executable statements left in this scop. 2787 simplifySCoP(true, DT, LI); 2788 if (Stmts.empty()) 2789 return; 2790 2791 // The ScopStmts now have enough information to initialize themselves. 2792 for (ScopStmt &Stmt : Stmts) 2793 Stmt.init(SD); 2794 2795 buildSchedule(SD, LI); 2796 2797 if (!hasFeasibleRuntimeContext()) 2798 return; 2799 2800 updateAccessDimensionality(); 2801 realignParams(); 2802 addParameterBounds(); 2803 addUserContext(); 2804 addWrappingContext(); 2805 simplifyContexts(); 2806 buildAliasChecks(AA); 2807 2808 hoistInvariantLoads(SD); 2809 verifyInvariantLoads(SD); 2810 simplifySCoP(false, DT, LI); 2811 } 2812 2813 Scop::~Scop() { 2814 isl_set_free(Context); 2815 isl_set_free(AssumedContext); 2816 isl_set_free(InvalidContext); 2817 isl_schedule_free(Schedule); 2818 2819 for (auto It : DomainMap) 2820 isl_set_free(It.second); 2821 2822 // Free the alias groups 2823 for (MinMaxVectorPairTy &MinMaxAccessPair : MinMaxAliasGroups) { 2824 for (MinMaxAccessTy &MMA : MinMaxAccessPair.first) { 2825 isl_pw_multi_aff_free(MMA.first); 2826 isl_pw_multi_aff_free(MMA.second); 2827 } 2828 for (MinMaxAccessTy &MMA : MinMaxAccessPair.second) { 2829 isl_pw_multi_aff_free(MMA.first); 2830 isl_pw_multi_aff_free(MMA.second); 2831 } 2832 } 2833 2834 for (const auto &IAClass : InvariantEquivClasses) 2835 isl_set_free(std::get<2>(IAClass)); 2836 2837 // Explicitly release all Scop objects and the underlying isl objects before 2838 // we relase the isl context. 2839 Stmts.clear(); 2840 ScopArrayInfoMap.clear(); 2841 AccFuncMap.clear(); 2842 } 2843 2844 void Scop::updateAccessDimensionality() { 2845 // Check all array accesses for each base pointer and find a (virtual) element 2846 // size for the base pointer that divides all access functions. 2847 for (auto &Stmt : *this) 2848 for (auto *Access : Stmt) { 2849 if (!Access->isArrayKind()) 2850 continue; 2851 auto &SAI = ScopArrayInfoMap[std::make_pair(Access->getBaseAddr(), 2852 ScopArrayInfo::MK_Array)]; 2853 if (SAI->getNumberOfDimensions() != 1) 2854 continue; 2855 unsigned DivisibleSize = SAI->getElemSizeInBytes(); 2856 auto *Subscript = Access->getSubscript(0); 2857 while (!isDivisible(Subscript, DivisibleSize, *SE)) 2858 DivisibleSize /= 2; 2859 auto *Ty = IntegerType::get(SE->getContext(), DivisibleSize * 8); 2860 SAI->updateElementType(Ty); 2861 } 2862 2863 for (auto &Stmt : *this) 2864 for (auto &Access : Stmt) 2865 Access->updateDimensionality(); 2866 } 2867 2868 void Scop::simplifySCoP(bool RemoveIgnoredStmts, DominatorTree &DT, 2869 LoopInfo &LI) { 2870 for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) { 2871 ScopStmt &Stmt = *StmtIt; 2872 RegionNode *RN = Stmt.getRegionNode(); 2873 2874 bool RemoveStmt = StmtIt->isEmpty(); 2875 if (!RemoveStmt) 2876 RemoveStmt = isl_set_is_empty(DomainMap[Stmt.getEntryBlock()]); 2877 if (!RemoveStmt) 2878 RemoveStmt = (RemoveIgnoredStmts && isIgnored(RN, DT, LI)); 2879 2880 // Remove read only statements only after invariant loop hoisting. 2881 if (!RemoveStmt && !RemoveIgnoredStmts) { 2882 bool OnlyRead = true; 2883 for (MemoryAccess *MA : Stmt) { 2884 if (MA->isRead()) 2885 continue; 2886 2887 OnlyRead = false; 2888 break; 2889 } 2890 2891 RemoveStmt = OnlyRead; 2892 } 2893 2894 if (RemoveStmt) { 2895 // Remove the statement because it is unnecessary. 2896 if (Stmt.isRegionStmt()) 2897 for (BasicBlock *BB : Stmt.getRegion()->blocks()) 2898 StmtMap.erase(BB); 2899 else 2900 StmtMap.erase(Stmt.getBasicBlock()); 2901 2902 StmtIt = Stmts.erase(StmtIt); 2903 continue; 2904 } 2905 2906 StmtIt++; 2907 } 2908 } 2909 2910 const InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) const { 2911 LoadInst *LInst = dyn_cast<LoadInst>(Val); 2912 if (!LInst) 2913 return nullptr; 2914 2915 if (Value *Rep = InvEquivClassVMap.lookup(LInst)) 2916 LInst = cast<LoadInst>(Rep); 2917 2918 Type *Ty = LInst->getType(); 2919 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 2920 for (auto &IAClass : InvariantEquivClasses) 2921 if (PointerSCEV == std::get<0>(IAClass) && Ty == std::get<3>(IAClass)) 2922 return &IAClass; 2923 2924 return nullptr; 2925 } 2926 2927 void Scop::addInvariantLoads(ScopStmt &Stmt, MemoryAccessList &InvMAs) { 2928 2929 // Get the context under which the statement is executed. 2930 isl_set *DomainCtx = isl_set_params(Stmt.getDomain()); 2931 DomainCtx = isl_set_remove_redundancies(DomainCtx); 2932 DomainCtx = isl_set_detect_equalities(DomainCtx); 2933 DomainCtx = isl_set_coalesce(DomainCtx); 2934 2935 // Project out all parameters that relate to loads in the statement. Otherwise 2936 // we could have cyclic dependences on the constraints under which the 2937 // hoisted loads are executed and we could not determine an order in which to 2938 // pre-load them. This happens because not only lower bounds are part of the 2939 // domain but also upper bounds. 2940 for (MemoryAccess *MA : InvMAs) { 2941 Instruction *AccInst = MA->getAccessInstruction(); 2942 if (SE->isSCEVable(AccInst->getType())) { 2943 SetVector<Value *> Values; 2944 for (const SCEV *Parameter : Parameters) { 2945 Values.clear(); 2946 findValues(Parameter, Values); 2947 if (!Values.count(AccInst)) 2948 continue; 2949 2950 if (isl_id *ParamId = getIdForParam(Parameter)) { 2951 int Dim = isl_set_find_dim_by_id(DomainCtx, isl_dim_param, ParamId); 2952 DomainCtx = isl_set_eliminate(DomainCtx, isl_dim_param, Dim, 1); 2953 isl_id_free(ParamId); 2954 } 2955 } 2956 } 2957 } 2958 2959 for (MemoryAccess *MA : InvMAs) { 2960 // Check for another invariant access that accesses the same location as 2961 // MA and if found consolidate them. Otherwise create a new equivalence 2962 // class at the end of InvariantEquivClasses. 2963 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction()); 2964 Type *Ty = LInst->getType(); 2965 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 2966 2967 bool Consolidated = false; 2968 for (auto &IAClass : InvariantEquivClasses) { 2969 if (PointerSCEV != std::get<0>(IAClass) || Ty != std::get<3>(IAClass)) 2970 continue; 2971 2972 Consolidated = true; 2973 2974 // Add MA to the list of accesses that are in this class. 2975 auto &MAs = std::get<1>(IAClass); 2976 MAs.push_front(MA); 2977 2978 // Unify the execution context of the class and this statement. 2979 isl_set *&IAClassDomainCtx = std::get<2>(IAClass); 2980 if (IAClassDomainCtx) 2981 IAClassDomainCtx = isl_set_coalesce( 2982 isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx))); 2983 else 2984 IAClassDomainCtx = isl_set_copy(DomainCtx); 2985 break; 2986 } 2987 2988 if (Consolidated) 2989 continue; 2990 2991 // If we did not consolidate MA, thus did not find an equivalence class 2992 // for it, we create a new one. 2993 InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA}, 2994 isl_set_copy(DomainCtx), Ty); 2995 } 2996 2997 isl_set_free(DomainCtx); 2998 } 2999 3000 bool Scop::isHoistableAccess(MemoryAccess *Access, 3001 __isl_keep isl_union_map *Writes) { 3002 // TODO: Loads that are not loop carried, hence are in a statement with 3003 // zero iterators, are by construction invariant, though we 3004 // currently "hoist" them anyway. This is necessary because we allow 3005 // them to be treated as parameters (e.g., in conditions) and our code 3006 // generation would otherwise use the old value. 3007 3008 auto &Stmt = *Access->getStatement(); 3009 BasicBlock *BB = Stmt.getEntryBlock(); 3010 3011 if (Access->isScalarKind() || Access->isWrite() || !Access->isAffine()) 3012 return false; 3013 3014 // Skip accesses that have an invariant base pointer which is defined but 3015 // not loaded inside the SCoP. This can happened e.g., if a readnone call 3016 // returns a pointer that is used as a base address. However, as we want 3017 // to hoist indirect pointers, we allow the base pointer to be defined in 3018 // the region if it is also a memory access. Each ScopArrayInfo object 3019 // that has a base pointer origin has a base pointer that is loaded and 3020 // that it is invariant, thus it will be hoisted too. However, if there is 3021 // no base pointer origin we check that the base pointer is defined 3022 // outside the region. 3023 const ScopArrayInfo *SAI = Access->getScopArrayInfo(); 3024 auto *BasePtrInst = dyn_cast<Instruction>(SAI->getBasePtr()); 3025 if (SAI->getBasePtrOriginSAI()) { 3026 assert(BasePtrInst && R.contains(BasePtrInst)); 3027 if (!isa<LoadInst>(BasePtrInst)) 3028 return false; 3029 auto *BasePtrStmt = getStmtFor(BasePtrInst); 3030 assert(BasePtrStmt); 3031 auto *BasePtrMA = BasePtrStmt->getArrayAccessOrNULLFor(BasePtrInst); 3032 if (BasePtrMA && !isHoistableAccess(BasePtrMA, Writes)) 3033 return false; 3034 } else if (BasePtrInst && R.contains(BasePtrInst)) 3035 return false; 3036 3037 // Skip accesses in non-affine subregions as they might not be executed 3038 // under the same condition as the entry of the non-affine subregion. 3039 if (BB != Access->getAccessInstruction()->getParent()) 3040 return false; 3041 3042 isl_map *AccessRelation = Access->getAccessRelation(); 3043 3044 // Skip accesses that have an empty access relation. These can be caused 3045 // by multiple offsets with a type cast in-between that cause the overall 3046 // byte offset to be not divisible by the new types sizes. 3047 if (isl_map_is_empty(AccessRelation)) { 3048 isl_map_free(AccessRelation); 3049 return false; 3050 } 3051 3052 if (isl_map_involves_dims(AccessRelation, isl_dim_in, 0, 3053 Stmt.getNumIterators())) { 3054 isl_map_free(AccessRelation); 3055 return false; 3056 } 3057 3058 AccessRelation = isl_map_intersect_domain(AccessRelation, Stmt.getDomain()); 3059 isl_set *AccessRange = isl_map_range(AccessRelation); 3060 3061 isl_union_map *Written = isl_union_map_intersect_range( 3062 isl_union_map_copy(Writes), isl_union_set_from_set(AccessRange)); 3063 bool IsWritten = !isl_union_map_is_empty(Written); 3064 isl_union_map_free(Written); 3065 3066 if (IsWritten) 3067 return false; 3068 3069 return true; 3070 } 3071 3072 void Scop::verifyInvariantLoads(ScopDetection &SD) { 3073 auto &RIL = *SD.getRequiredInvariantLoads(&getRegion()); 3074 for (LoadInst *LI : RIL) { 3075 assert(LI && getRegion().contains(LI)); 3076 ScopStmt *Stmt = getStmtFor(LI); 3077 if (Stmt && Stmt->getArrayAccessOrNULLFor(LI)) { 3078 invalidate(INVARIANTLOAD, LI->getDebugLoc()); 3079 return; 3080 } 3081 } 3082 } 3083 3084 void Scop::hoistInvariantLoads(ScopDetection &SD) { 3085 if (!PollyInvariantLoadHoisting) 3086 return; 3087 3088 isl_union_map *Writes = getWrites(); 3089 for (ScopStmt &Stmt : *this) { 3090 MemoryAccessList InvariantAccesses; 3091 3092 for (MemoryAccess *Access : Stmt) 3093 if (isHoistableAccess(Access, Writes)) 3094 InvariantAccesses.push_front(Access); 3095 3096 // We inserted invariant accesses always in the front but need them to be 3097 // sorted in a "natural order". The statements are already sorted in 3098 // reverse post order and that suffices for the accesses too. The reason 3099 // we require an order in the first place is the dependences between 3100 // invariant loads that can be caused by indirect loads. 3101 InvariantAccesses.reverse(); 3102 3103 // Transfer the memory access from the statement to the SCoP. 3104 Stmt.removeMemoryAccesses(InvariantAccesses); 3105 addInvariantLoads(Stmt, InvariantAccesses); 3106 } 3107 isl_union_map_free(Writes); 3108 } 3109 3110 const ScopArrayInfo * 3111 Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, 3112 ArrayRef<const SCEV *> Sizes, 3113 ScopArrayInfo::MemoryKind Kind) { 3114 auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]; 3115 if (!SAI) { 3116 auto &DL = getRegion().getEntry()->getModule()->getDataLayout(); 3117 SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind, 3118 DL, this)); 3119 } else { 3120 SAI->updateElementType(ElementType); 3121 // In case of mismatching array sizes, we bail out by setting the run-time 3122 // context to false. 3123 if (!SAI->updateSizes(Sizes)) 3124 invalidate(DELINEARIZATION, DebugLoc()); 3125 } 3126 return SAI.get(); 3127 } 3128 3129 const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, 3130 ScopArrayInfo::MemoryKind Kind) { 3131 auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get(); 3132 assert(SAI && "No ScopArrayInfo available for this base pointer"); 3133 return SAI; 3134 } 3135 3136 std::string Scop::getContextStr() const { return stringFromIslObj(Context); } 3137 3138 std::string Scop::getAssumedContextStr() const { 3139 assert(AssumedContext && "Assumed context not yet built"); 3140 return stringFromIslObj(AssumedContext); 3141 } 3142 3143 std::string Scop::getInvalidContextStr() const { 3144 return stringFromIslObj(InvalidContext); 3145 } 3146 3147 std::string Scop::getNameStr() const { 3148 std::string ExitName, EntryName; 3149 raw_string_ostream ExitStr(ExitName); 3150 raw_string_ostream EntryStr(EntryName); 3151 3152 R.getEntry()->printAsOperand(EntryStr, false); 3153 EntryStr.str(); 3154 3155 if (R.getExit()) { 3156 R.getExit()->printAsOperand(ExitStr, false); 3157 ExitStr.str(); 3158 } else 3159 ExitName = "FunctionExit"; 3160 3161 return EntryName + "---" + ExitName; 3162 } 3163 3164 __isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); } 3165 __isl_give isl_space *Scop::getParamSpace() const { 3166 return isl_set_get_space(Context); 3167 } 3168 3169 __isl_give isl_set *Scop::getAssumedContext() const { 3170 assert(AssumedContext && "Assumed context not yet built"); 3171 return isl_set_copy(AssumedContext); 3172 } 3173 3174 bool Scop::hasFeasibleRuntimeContext() const { 3175 auto *PositiveContext = getAssumedContext(); 3176 PositiveContext = addNonEmptyDomainConstraints(PositiveContext); 3177 bool IsFeasible = !isl_set_is_empty(PositiveContext); 3178 isl_set_free(PositiveContext); 3179 if (!IsFeasible) 3180 return false; 3181 3182 auto *NegativeContext = getInvalidContext(); 3183 auto *DomainContext = isl_union_set_params(getDomains()); 3184 IsFeasible = !isl_set_is_subset(DomainContext, NegativeContext); 3185 isl_set_free(NegativeContext); 3186 isl_set_free(DomainContext); 3187 3188 return IsFeasible; 3189 } 3190 3191 static std::string toString(AssumptionKind Kind) { 3192 switch (Kind) { 3193 case ALIASING: 3194 return "No-aliasing"; 3195 case INBOUNDS: 3196 return "Inbounds"; 3197 case WRAPPING: 3198 return "No-overflows"; 3199 case ERRORBLOCK: 3200 return "No-error"; 3201 case INFINITELOOP: 3202 return "Finite loop"; 3203 case INVARIANTLOAD: 3204 return "Invariant load"; 3205 case DELINEARIZATION: 3206 return "Delinearization"; 3207 case ERROR_DOMAINCONJUNCTS: 3208 return "Low number of domain conjuncts"; 3209 } 3210 llvm_unreachable("Unknown AssumptionKind!"); 3211 } 3212 3213 bool Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, 3214 DebugLoc Loc, AssumptionSign Sign) { 3215 if (Sign == AS_ASSUMPTION) { 3216 if (isl_set_is_subset(Context, Set)) 3217 return false; 3218 3219 if (isl_set_is_subset(AssumedContext, Set)) 3220 return false; 3221 } else { 3222 if (isl_set_is_disjoint(Set, Context)) 3223 return false; 3224 3225 if (isl_set_is_subset(Set, InvalidContext)) 3226 return false; 3227 } 3228 3229 auto &F = *getRegion().getEntry()->getParent(); 3230 auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t"; 3231 std::string Msg = toString(Kind) + Suffix + stringFromIslObj(Set); 3232 emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, Loc, Msg); 3233 return true; 3234 } 3235 3236 void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, 3237 DebugLoc Loc, AssumptionSign Sign) { 3238 if (!trackAssumption(Kind, Set, Loc, Sign)) { 3239 isl_set_free(Set); 3240 return; 3241 } 3242 3243 if (Sign == AS_ASSUMPTION) { 3244 AssumedContext = isl_set_intersect(AssumedContext, Set); 3245 AssumedContext = isl_set_coalesce(AssumedContext); 3246 } else { 3247 InvalidContext = isl_set_union(InvalidContext, Set); 3248 InvalidContext = isl_set_coalesce(InvalidContext); 3249 } 3250 } 3251 3252 void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc) { 3253 addAssumption(Kind, isl_set_empty(getParamSpace()), Loc, AS_ASSUMPTION); 3254 } 3255 3256 __isl_give isl_set *Scop::getInvalidContext() const { 3257 return isl_set_copy(InvalidContext); 3258 } 3259 3260 void Scop::printContext(raw_ostream &OS) const { 3261 OS << "Context:\n"; 3262 OS.indent(4) << Context << "\n"; 3263 3264 OS.indent(4) << "Assumed Context:\n"; 3265 OS.indent(4) << AssumedContext << "\n"; 3266 3267 OS.indent(4) << "Invalid Context:\n"; 3268 OS.indent(4) << InvalidContext << "\n"; 3269 3270 for (const SCEV *Parameter : Parameters) { 3271 int Dim = ParameterIds.find(Parameter)->second; 3272 OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n"; 3273 } 3274 } 3275 3276 void Scop::printAliasAssumptions(raw_ostream &OS) const { 3277 int noOfGroups = 0; 3278 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 3279 if (Pair.second.size() == 0) 3280 noOfGroups += 1; 3281 else 3282 noOfGroups += Pair.second.size(); 3283 } 3284 3285 OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n"; 3286 if (MinMaxAliasGroups.empty()) { 3287 OS.indent(8) << "n/a\n"; 3288 return; 3289 } 3290 3291 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 3292 3293 // If the group has no read only accesses print the write accesses. 3294 if (Pair.second.empty()) { 3295 OS.indent(8) << "[["; 3296 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 3297 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 3298 << ">"; 3299 } 3300 OS << " ]]\n"; 3301 } 3302 3303 for (const MinMaxAccessTy &MMAReadOnly : Pair.second) { 3304 OS.indent(8) << "[["; 3305 OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">"; 3306 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 3307 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 3308 << ">"; 3309 } 3310 OS << " ]]\n"; 3311 } 3312 } 3313 } 3314 3315 void Scop::printStatements(raw_ostream &OS) const { 3316 OS << "Statements {\n"; 3317 3318 for (const ScopStmt &Stmt : *this) 3319 OS.indent(4) << Stmt; 3320 3321 OS.indent(4) << "}\n"; 3322 } 3323 3324 void Scop::printArrayInfo(raw_ostream &OS) const { 3325 OS << "Arrays {\n"; 3326 3327 for (auto &Array : arrays()) 3328 Array.second->print(OS); 3329 3330 OS.indent(4) << "}\n"; 3331 3332 OS.indent(4) << "Arrays (Bounds as pw_affs) {\n"; 3333 3334 for (auto &Array : arrays()) 3335 Array.second->print(OS, /* SizeAsPwAff */ true); 3336 3337 OS.indent(4) << "}\n"; 3338 } 3339 3340 void Scop::print(raw_ostream &OS) const { 3341 OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName() 3342 << "\n"; 3343 OS.indent(4) << "Region: " << getNameStr() << "\n"; 3344 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; 3345 OS.indent(4) << "Invariant Accesses: {\n"; 3346 for (const auto &IAClass : InvariantEquivClasses) { 3347 const auto &MAs = std::get<1>(IAClass); 3348 if (MAs.empty()) { 3349 OS.indent(12) << "Class Pointer: " << *std::get<0>(IAClass) << "\n"; 3350 } else { 3351 MAs.front()->print(OS); 3352 OS.indent(12) << "Execution Context: " << std::get<2>(IAClass) << "\n"; 3353 } 3354 } 3355 OS.indent(4) << "}\n"; 3356 printContext(OS.indent(4)); 3357 printArrayInfo(OS.indent(4)); 3358 printAliasAssumptions(OS); 3359 printStatements(OS.indent(4)); 3360 } 3361 3362 void Scop::dump() const { print(dbgs()); } 3363 3364 isl_ctx *Scop::getIslCtx() const { return IslCtx.get(); } 3365 3366 __isl_give isl_pw_aff *Scop::getPwAff(const SCEV *E, BasicBlock *BB) { 3367 return Affinator.getPwAff(E, BB); 3368 } 3369 3370 __isl_give isl_union_set *Scop::getDomains() const { 3371 isl_union_set *Domain = isl_union_set_empty(getParamSpace()); 3372 3373 for (const ScopStmt &Stmt : *this) 3374 Domain = isl_union_set_add_set(Domain, Stmt.getDomain()); 3375 3376 return Domain; 3377 } 3378 3379 __isl_give isl_union_map * 3380 Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) { 3381 isl_union_map *Accesses = isl_union_map_empty(getParamSpace()); 3382 3383 for (ScopStmt &Stmt : *this) { 3384 for (MemoryAccess *MA : Stmt) { 3385 if (!Predicate(*MA)) 3386 continue; 3387 3388 isl_set *Domain = Stmt.getDomain(); 3389 isl_map *AccessDomain = MA->getAccessRelation(); 3390 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain); 3391 Accesses = isl_union_map_add_map(Accesses, AccessDomain); 3392 } 3393 } 3394 return isl_union_map_coalesce(Accesses); 3395 } 3396 3397 __isl_give isl_union_map *Scop::getMustWrites() { 3398 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); }); 3399 } 3400 3401 __isl_give isl_union_map *Scop::getMayWrites() { 3402 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); }); 3403 } 3404 3405 __isl_give isl_union_map *Scop::getWrites() { 3406 return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); }); 3407 } 3408 3409 __isl_give isl_union_map *Scop::getReads() { 3410 return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); }); 3411 } 3412 3413 __isl_give isl_union_map *Scop::getAccesses() { 3414 return getAccessesOfType([](MemoryAccess &MA) { return true; }); 3415 } 3416 3417 __isl_give isl_union_map *Scop::getSchedule() const { 3418 auto *Tree = getScheduleTree(); 3419 auto *S = isl_schedule_get_map(Tree); 3420 isl_schedule_free(Tree); 3421 return S; 3422 } 3423 3424 __isl_give isl_schedule *Scop::getScheduleTree() const { 3425 return isl_schedule_intersect_domain(isl_schedule_copy(Schedule), 3426 getDomains()); 3427 } 3428 3429 void Scop::setSchedule(__isl_take isl_union_map *NewSchedule) { 3430 auto *S = isl_schedule_from_domain(getDomains()); 3431 S = isl_schedule_insert_partial_schedule( 3432 S, isl_multi_union_pw_aff_from_union_map(NewSchedule)); 3433 isl_schedule_free(Schedule); 3434 Schedule = S; 3435 } 3436 3437 void Scop::setScheduleTree(__isl_take isl_schedule *NewSchedule) { 3438 isl_schedule_free(Schedule); 3439 Schedule = NewSchedule; 3440 } 3441 3442 bool Scop::restrictDomains(__isl_take isl_union_set *Domain) { 3443 bool Changed = false; 3444 for (ScopStmt &Stmt : *this) { 3445 isl_union_set *StmtDomain = isl_union_set_from_set(Stmt.getDomain()); 3446 isl_union_set *NewStmtDomain = isl_union_set_intersect( 3447 isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain)); 3448 3449 if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) { 3450 isl_union_set_free(StmtDomain); 3451 isl_union_set_free(NewStmtDomain); 3452 continue; 3453 } 3454 3455 Changed = true; 3456 3457 isl_union_set_free(StmtDomain); 3458 NewStmtDomain = isl_union_set_coalesce(NewStmtDomain); 3459 3460 if (isl_union_set_is_empty(NewStmtDomain)) { 3461 Stmt.restrictDomain(isl_set_empty(Stmt.getDomainSpace())); 3462 isl_union_set_free(NewStmtDomain); 3463 } else 3464 Stmt.restrictDomain(isl_set_from_union_set(NewStmtDomain)); 3465 } 3466 isl_union_set_free(Domain); 3467 return Changed; 3468 } 3469 3470 ScalarEvolution *Scop::getSE() const { return SE; } 3471 3472 bool Scop::isIgnored(RegionNode *RN, DominatorTree &DT, LoopInfo &LI) { 3473 BasicBlock *BB = getRegionNodeBasicBlock(RN); 3474 ScopStmt *Stmt = getStmtFor(RN); 3475 3476 // If there is no stmt, then it already has been removed. 3477 if (!Stmt) 3478 return true; 3479 3480 // Check if there are accesses contained. 3481 if (Stmt->isEmpty()) 3482 return true; 3483 3484 // Check for reachability via non-error blocks. 3485 if (!DomainMap.count(BB)) 3486 return true; 3487 3488 // Check if error blocks are contained. 3489 if (containsErrorBlock(RN, getRegion(), LI, DT)) 3490 return true; 3491 3492 return false; 3493 } 3494 3495 struct MapToDimensionDataTy { 3496 int N; 3497 isl_union_pw_multi_aff *Res; 3498 }; 3499 3500 // @brief Create a function that maps the elements of 'Set' to its N-th 3501 // dimension and add it to User->Res. 3502 // 3503 // @param Set The input set. 3504 // @param User->N The dimension to map to. 3505 // @param User->Res The isl_union_pw_multi_aff to which to add the result. 3506 // 3507 // @returns isl_stat_ok if no error occured, othewise isl_stat_error. 3508 static isl_stat mapToDimension_AddSet(__isl_take isl_set *Set, void *User) { 3509 struct MapToDimensionDataTy *Data = (struct MapToDimensionDataTy *)User; 3510 int Dim; 3511 isl_space *Space; 3512 isl_pw_multi_aff *PMA; 3513 3514 Dim = isl_set_dim(Set, isl_dim_set); 3515 Space = isl_set_get_space(Set); 3516 PMA = isl_pw_multi_aff_project_out_map(Space, isl_dim_set, Data->N, 3517 Dim - Data->N); 3518 if (Data->N > 1) 3519 PMA = isl_pw_multi_aff_drop_dims(PMA, isl_dim_out, 0, Data->N - 1); 3520 Data->Res = isl_union_pw_multi_aff_add_pw_multi_aff(Data->Res, PMA); 3521 3522 isl_set_free(Set); 3523 3524 return isl_stat_ok; 3525 } 3526 3527 // @brief Create an isl_multi_union_aff that defines an identity mapping 3528 // from the elements of USet to their N-th dimension. 3529 // 3530 // # Example: 3531 // 3532 // Domain: { A[i,j]; B[i,j,k] } 3533 // N: 1 3534 // 3535 // Resulting Mapping: { {A[i,j] -> [(j)]; B[i,j,k] -> [(j)] } 3536 // 3537 // @param USet A union set describing the elements for which to generate a 3538 // mapping. 3539 // @param N The dimension to map to. 3540 // @returns A mapping from USet to its N-th dimension. 3541 static __isl_give isl_multi_union_pw_aff * 3542 mapToDimension(__isl_take isl_union_set *USet, int N) { 3543 assert(N >= 0); 3544 assert(USet); 3545 assert(!isl_union_set_is_empty(USet)); 3546 3547 struct MapToDimensionDataTy Data; 3548 3549 auto *Space = isl_union_set_get_space(USet); 3550 auto *PwAff = isl_union_pw_multi_aff_empty(Space); 3551 3552 Data = {N, PwAff}; 3553 3554 auto Res = isl_union_set_foreach_set(USet, &mapToDimension_AddSet, &Data); 3555 (void)Res; 3556 3557 assert(Res == isl_stat_ok); 3558 3559 isl_union_set_free(USet); 3560 return isl_multi_union_pw_aff_from_union_pw_multi_aff(Data.Res); 3561 } 3562 3563 void Scop::addScopStmt(BasicBlock *BB, Region *R) { 3564 if (BB) { 3565 Stmts.emplace_back(*this, *BB); 3566 auto *Stmt = &Stmts.back(); 3567 StmtMap[BB] = Stmt; 3568 } else { 3569 assert(R && "Either basic block or a region expected."); 3570 Stmts.emplace_back(*this, *R); 3571 auto *Stmt = &Stmts.back(); 3572 for (BasicBlock *BB : R->blocks()) 3573 StmtMap[BB] = Stmt; 3574 } 3575 } 3576 3577 void Scop::buildSchedule(ScopDetection &SD, LoopInfo &LI) { 3578 Loop *L = getLoopSurroundingRegion(getRegion(), LI); 3579 LoopStackTy LoopStack({LoopStackElementTy(L, nullptr, 0)}); 3580 buildSchedule(getRegion().getNode(), LoopStack, SD, LI); 3581 assert(LoopStack.size() == 1 && LoopStack.back().L == L); 3582 Schedule = LoopStack[0].Schedule; 3583 } 3584 3585 /// To generate a schedule for the elements in a Region we traverse the Region 3586 /// in reverse-post-order and add the contained RegionNodes in traversal order 3587 /// to the schedule of the loop that is currently at the top of the LoopStack. 3588 /// For loop-free codes, this results in a correct sequential ordering. 3589 /// 3590 /// Example: 3591 /// bb1(0) 3592 /// / \. 3593 /// bb2(1) bb3(2) 3594 /// \ / \. 3595 /// bb4(3) bb5(4) 3596 /// \ / 3597 /// bb6(5) 3598 /// 3599 /// Including loops requires additional processing. Whenever a loop header is 3600 /// encountered, the corresponding loop is added to the @p LoopStack. Starting 3601 /// from an empty schedule, we first process all RegionNodes that are within 3602 /// this loop and complete the sequential schedule at this loop-level before 3603 /// processing about any other nodes. To implement this 3604 /// loop-nodes-first-processing, the reverse post-order traversal is 3605 /// insufficient. Hence, we additionally check if the traversal yields 3606 /// sub-regions or blocks that are outside the last loop on the @p LoopStack. 3607 /// These region-nodes are then queue and only traverse after the all nodes 3608 /// within the current loop have been processed. 3609 void Scop::buildSchedule(Region *R, LoopStackTy &LoopStack, ScopDetection &SD, 3610 LoopInfo &LI) { 3611 Loop *OuterScopLoop = getLoopSurroundingRegion(getRegion(), LI); 3612 3613 ReversePostOrderTraversal<Region *> RTraversal(R); 3614 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end()); 3615 std::deque<RegionNode *> DelayList; 3616 bool LastRNWaiting = false; 3617 3618 // Iterate over the region @p R in reverse post-order but queue 3619 // sub-regions/blocks iff they are not part of the last encountered but not 3620 // completely traversed loop. The variable LastRNWaiting is a flag to indicate 3621 // that we queued the last sub-region/block from the reverse post-order 3622 // iterator. If it is set we have to explore the next sub-region/block from 3623 // the iterator (if any) to guarantee progress. If it is not set we first try 3624 // the next queued sub-region/blocks. 3625 while (!WorkList.empty() || !DelayList.empty()) { 3626 RegionNode *RN; 3627 3628 if ((LastRNWaiting && !WorkList.empty()) || DelayList.size() == 0) { 3629 RN = WorkList.front(); 3630 WorkList.pop_front(); 3631 LastRNWaiting = false; 3632 } else { 3633 RN = DelayList.front(); 3634 DelayList.pop_front(); 3635 } 3636 3637 Loop *L = getRegionNodeLoop(RN, LI); 3638 if (!getRegion().contains(L)) 3639 L = OuterScopLoop; 3640 3641 Loop *LastLoop = LoopStack.back().L; 3642 if (LastLoop != L) { 3643 if (!LastLoop->contains(L)) { 3644 LastRNWaiting = true; 3645 DelayList.push_back(RN); 3646 continue; 3647 } 3648 LoopStack.push_back({L, nullptr, 0}); 3649 } 3650 buildSchedule(RN, LoopStack, SD, LI); 3651 } 3652 3653 return; 3654 } 3655 3656 void Scop::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack, 3657 ScopDetection &SD, LoopInfo &LI) { 3658 3659 if (RN->isSubRegion()) { 3660 auto *LocalRegion = RN->getNodeAs<Region>(); 3661 if (!SD.isNonAffineSubRegion(LocalRegion, &getRegion())) { 3662 buildSchedule(LocalRegion, LoopStack, SD, LI); 3663 return; 3664 } 3665 } 3666 3667 auto &LoopData = LoopStack.back(); 3668 LoopData.NumBlocksProcessed += getNumBlocksInRegionNode(RN); 3669 3670 if (auto *Stmt = getStmtFor(RN)) { 3671 auto *UDomain = isl_union_set_from_set(Stmt->getDomain()); 3672 auto *StmtSchedule = isl_schedule_from_domain(UDomain); 3673 LoopData.Schedule = combineInSequence(LoopData.Schedule, StmtSchedule); 3674 } 3675 3676 // Check if we just processed the last node in this loop. If we did, finalize 3677 // the loop by: 3678 // 3679 // - adding new schedule dimensions 3680 // - folding the resulting schedule into the parent loop schedule 3681 // - dropping the loop schedule from the LoopStack. 3682 // 3683 // Then continue to check surrounding loops, which might also have been 3684 // completed by this node. 3685 while (LoopData.L && 3686 LoopData.NumBlocksProcessed == LoopData.L->getNumBlocks()) { 3687 auto *Schedule = LoopData.Schedule; 3688 auto NumBlocksProcessed = LoopData.NumBlocksProcessed; 3689 3690 LoopStack.pop_back(); 3691 auto &NextLoopData = LoopStack.back(); 3692 3693 if (Schedule) { 3694 auto *Domain = isl_schedule_get_domain(Schedule); 3695 auto *MUPA = mapToDimension(Domain, LoopStack.size()); 3696 Schedule = isl_schedule_insert_partial_schedule(Schedule, MUPA); 3697 NextLoopData.Schedule = 3698 combineInSequence(NextLoopData.Schedule, Schedule); 3699 } 3700 3701 NextLoopData.NumBlocksProcessed += NumBlocksProcessed; 3702 LoopData = NextLoopData; 3703 } 3704 } 3705 3706 ScopStmt *Scop::getStmtFor(BasicBlock *BB) const { 3707 auto StmtMapIt = StmtMap.find(BB); 3708 if (StmtMapIt == StmtMap.end()) 3709 return nullptr; 3710 return StmtMapIt->second; 3711 } 3712 3713 ScopStmt *Scop::getStmtFor(RegionNode *RN) const { 3714 if (RN->isSubRegion()) 3715 return getStmtFor(RN->getNodeAs<Region>()); 3716 return getStmtFor(RN->getNodeAs<BasicBlock>()); 3717 } 3718 3719 ScopStmt *Scop::getStmtFor(Region *R) const { 3720 ScopStmt *Stmt = getStmtFor(R->getEntry()); 3721 assert(!Stmt || Stmt->getRegion() == R); 3722 return Stmt; 3723 } 3724 3725 int Scop::getRelativeLoopDepth(const Loop *L) const { 3726 Loop *OuterLoop = 3727 L ? R.outermostLoopInRegion(const_cast<Loop *>(L)) : nullptr; 3728 if (!OuterLoop) 3729 return -1; 3730 return L->getLoopDepth() - OuterLoop->getLoopDepth(); 3731 } 3732 3733 void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R, 3734 Region *NonAffineSubRegion, bool IsExitBlock) { 3735 3736 // PHI nodes that are in the exit block of the region, hence if IsExitBlock is 3737 // true, are not modeled as ordinary PHI nodes as they are not part of the 3738 // region. However, we model the operands in the predecessor blocks that are 3739 // part of the region as regular scalar accesses. 3740 3741 // If we can synthesize a PHI we can skip it, however only if it is in 3742 // the region. If it is not it can only be in the exit block of the region. 3743 // In this case we model the operands but not the PHI itself. 3744 auto *Scope = LI->getLoopFor(PHI->getParent()); 3745 if (!IsExitBlock && canSynthesize(PHI, LI, SE, &R, Scope)) 3746 return; 3747 3748 // PHI nodes are modeled as if they had been demoted prior to the SCoP 3749 // detection. Hence, the PHI is a load of a new memory location in which the 3750 // incoming value was written at the end of the incoming basic block. 3751 bool OnlyNonAffineSubRegionOperands = true; 3752 for (unsigned u = 0; u < PHI->getNumIncomingValues(); u++) { 3753 Value *Op = PHI->getIncomingValue(u); 3754 BasicBlock *OpBB = PHI->getIncomingBlock(u); 3755 3756 // Do not build scalar dependences inside a non-affine subregion. 3757 if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB)) 3758 continue; 3759 3760 OnlyNonAffineSubRegionOperands = false; 3761 ensurePHIWrite(PHI, OpBB, Op, IsExitBlock); 3762 } 3763 3764 if (!OnlyNonAffineSubRegionOperands && !IsExitBlock) { 3765 addPHIReadAccess(PHI); 3766 } 3767 } 3768 3769 void ScopInfo::buildScalarDependences(Instruction *Inst) { 3770 assert(!isa<PHINode>(Inst)); 3771 3772 // Pull-in required operands. 3773 for (Use &Op : Inst->operands()) 3774 ensureValueRead(Op.get(), Inst->getParent()); 3775 } 3776 3777 void ScopInfo::buildEscapingDependences(Instruction *Inst) { 3778 Region *R = &scop->getRegion(); 3779 3780 // Check for uses of this instruction outside the scop. Because we do not 3781 // iterate over such instructions and therefore did not "ensure" the existence 3782 // of a write, we must determine such use here. 3783 for (Use &U : Inst->uses()) { 3784 Instruction *UI = dyn_cast<Instruction>(U.getUser()); 3785 if (!UI) 3786 continue; 3787 3788 BasicBlock *UseParent = getUseBlock(U); 3789 BasicBlock *UserParent = UI->getParent(); 3790 3791 // An escaping value is either used by an instruction not within the scop, 3792 // or (when the scop region's exit needs to be simplified) by a PHI in the 3793 // scop's exit block. This is because region simplification before code 3794 // generation inserts new basic blocks before the PHI such that its incoming 3795 // blocks are not in the scop anymore. 3796 if (!R->contains(UseParent) || 3797 (isa<PHINode>(UI) && UserParent == R->getExit() && 3798 R->getExitingBlock())) { 3799 // At least one escaping use found. 3800 ensureValueWrite(Inst); 3801 break; 3802 } 3803 } 3804 } 3805 3806 bool ScopInfo::buildAccessMultiDimFixed( 3807 MemAccInst Inst, Loop *L, Region *R, 3808 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3809 const InvariantLoadsSetTy &ScopRIL) { 3810 Value *Val = Inst.getValueOperand(); 3811 Type *ElementType = Val->getType(); 3812 Value *Address = Inst.getPointerOperand(); 3813 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); 3814 const SCEVUnknown *BasePointer = 3815 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction)); 3816 enum MemoryAccess::AccessType Type = 3817 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; 3818 3819 if (auto *BitCast = dyn_cast<BitCastInst>(Address)) { 3820 auto *Src = BitCast->getOperand(0); 3821 auto *SrcTy = Src->getType(); 3822 auto *DstTy = BitCast->getType(); 3823 if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits()) 3824 Address = Src; 3825 } 3826 3827 auto *GEP = dyn_cast<GetElementPtrInst>(Address); 3828 if (!GEP) 3829 return false; 3830 3831 std::vector<const SCEV *> Subscripts; 3832 std::vector<int> Sizes; 3833 std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP, *SE); 3834 auto *BasePtr = GEP->getOperand(0); 3835 3836 std::vector<const SCEV *> SizesSCEV; 3837 3838 for (auto *Subscript : Subscripts) { 3839 InvariantLoadsSetTy AccessILS; 3840 if (!isAffineExpr(R, Subscript, *SE, nullptr, &AccessILS)) 3841 return false; 3842 3843 for (LoadInst *LInst : AccessILS) 3844 if (!ScopRIL.count(LInst)) 3845 return false; 3846 } 3847 3848 if (Sizes.empty()) 3849 return false; 3850 3851 for (auto V : Sizes) 3852 SizesSCEV.push_back(SE->getSCEV( 3853 ConstantInt::get(IntegerType::getInt64Ty(BasePtr->getContext()), V))); 3854 3855 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementType, true, 3856 Subscripts, SizesSCEV, Val); 3857 return true; 3858 } 3859 3860 bool ScopInfo::buildAccessMultiDimParam( 3861 MemAccInst Inst, Loop *L, Region *R, 3862 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3863 const InvariantLoadsSetTy &ScopRIL, const MapInsnToMemAcc &InsnToMemAcc) { 3864 if (!PollyDelinearize) 3865 return false; 3866 3867 Value *Address = Inst.getPointerOperand(); 3868 Value *Val = Inst.getValueOperand(); 3869 Type *ElementType = Val->getType(); 3870 unsigned ElementSize = DL->getTypeAllocSize(ElementType); 3871 enum MemoryAccess::AccessType Type = 3872 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; 3873 3874 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); 3875 const SCEVUnknown *BasePointer = 3876 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction)); 3877 3878 assert(BasePointer && "Could not find base pointer"); 3879 AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer); 3880 3881 auto AccItr = InsnToMemAcc.find(Inst); 3882 if (AccItr == InsnToMemAcc.end()) 3883 return false; 3884 3885 std::vector<const SCEV *> Sizes( 3886 AccItr->second.Shape->DelinearizedSizes.begin(), 3887 AccItr->second.Shape->DelinearizedSizes.end()); 3888 // Remove the element size. This information is already provided by the 3889 // ElementSize parameter. In case the element size of this access and the 3890 // element size used for delinearization differs the delinearization is 3891 // incorrect. Hence, we invalidate the scop. 3892 // 3893 // TODO: Handle delinearization with differing element sizes. 3894 auto DelinearizedSize = 3895 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue(); 3896 Sizes.pop_back(); 3897 if (ElementSize != DelinearizedSize) 3898 scop->invalidate(DELINEARIZATION, Inst->getDebugLoc()); 3899 3900 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementType, true, 3901 AccItr->second.DelinearizedSubscripts, Sizes, Val); 3902 return true; 3903 } 3904 3905 bool ScopInfo::buildAccessMemIntrinsic( 3906 MemAccInst Inst, Loop *L, Region *R, 3907 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3908 const InvariantLoadsSetTy &ScopRIL) { 3909 auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst); 3910 3911 if (MemIntr == nullptr) 3912 return false; 3913 3914 auto *LengthVal = SE->getSCEVAtScope(MemIntr->getLength(), L); 3915 assert(LengthVal); 3916 3917 // Check if the length val is actually affine or if we overapproximate it 3918 InvariantLoadsSetTy AccessILS; 3919 bool LengthIsAffine = isAffineExpr(R, LengthVal, *SE, nullptr, &AccessILS); 3920 for (LoadInst *LInst : AccessILS) 3921 if (!ScopRIL.count(LInst)) 3922 LengthIsAffine = false; 3923 if (!LengthIsAffine) 3924 LengthVal = nullptr; 3925 3926 auto *DestPtrVal = MemIntr->getDest(); 3927 assert(DestPtrVal); 3928 auto *DestAccFunc = SE->getSCEVAtScope(DestPtrVal, L); 3929 assert(DestAccFunc); 3930 auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(SE->getPointerBase(DestAccFunc)); 3931 assert(DestPtrSCEV); 3932 DestAccFunc = SE->getMinusSCEV(DestAccFunc, DestPtrSCEV); 3933 addArrayAccess(Inst, MemoryAccess::MUST_WRITE, DestPtrSCEV->getValue(), 3934 IntegerType::getInt8Ty(DestPtrVal->getContext()), false, 3935 {DestAccFunc, LengthVal}, {}, Inst.getValueOperand()); 3936 3937 auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr); 3938 if (!MemTrans) 3939 return true; 3940 3941 auto *SrcPtrVal = MemTrans->getSource(); 3942 assert(SrcPtrVal); 3943 auto *SrcAccFunc = SE->getSCEVAtScope(SrcPtrVal, L); 3944 assert(SrcAccFunc); 3945 auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(SE->getPointerBase(SrcAccFunc)); 3946 assert(SrcPtrSCEV); 3947 SrcAccFunc = SE->getMinusSCEV(SrcAccFunc, SrcPtrSCEV); 3948 addArrayAccess(Inst, MemoryAccess::READ, SrcPtrSCEV->getValue(), 3949 IntegerType::getInt8Ty(SrcPtrVal->getContext()), false, 3950 {SrcAccFunc, LengthVal}, {}, Inst.getValueOperand()); 3951 3952 return true; 3953 } 3954 3955 bool ScopInfo::buildAccessCallInst( 3956 MemAccInst Inst, Loop *L, Region *R, 3957 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 3958 const InvariantLoadsSetTy &ScopRIL) { 3959 auto *CI = dyn_cast_or_null<CallInst>(Inst); 3960 3961 if (CI == nullptr) 3962 return false; 3963 3964 if (CI->doesNotAccessMemory() || isIgnoredIntrinsic(CI)) 3965 return true; 3966 3967 bool ReadOnly = false; 3968 auto *AF = SE->getConstant(IntegerType::getInt64Ty(CI->getContext()), 0); 3969 auto *CalledFunction = CI->getCalledFunction(); 3970 switch (AA->getModRefBehavior(CalledFunction)) { 3971 case llvm::FMRB_UnknownModRefBehavior: 3972 llvm_unreachable("Unknown mod ref behaviour cannot be represented."); 3973 case llvm::FMRB_DoesNotAccessMemory: 3974 return true; 3975 case llvm::FMRB_OnlyReadsMemory: 3976 GlobalReads.push_back(CI); 3977 return true; 3978 case llvm::FMRB_OnlyReadsArgumentPointees: 3979 ReadOnly = true; 3980 // Fall through 3981 case llvm::FMRB_OnlyAccessesArgumentPointees: 3982 auto AccType = ReadOnly ? MemoryAccess::READ : MemoryAccess::MAY_WRITE; 3983 for (const auto &Arg : CI->arg_operands()) { 3984 if (!Arg->getType()->isPointerTy()) 3985 continue; 3986 3987 auto *ArgSCEV = SE->getSCEVAtScope(Arg, L); 3988 if (ArgSCEV->isZero()) 3989 continue; 3990 3991 auto *ArgBasePtr = cast<SCEVUnknown>(SE->getPointerBase(ArgSCEV)); 3992 addArrayAccess(Inst, AccType, ArgBasePtr->getValue(), 3993 ArgBasePtr->getType(), false, {AF}, {}, CI); 3994 } 3995 return true; 3996 } 3997 3998 return true; 3999 } 4000 4001 void ScopInfo::buildAccessSingleDim( 4002 MemAccInst Inst, Loop *L, Region *R, 4003 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 4004 const InvariantLoadsSetTy &ScopRIL) { 4005 Value *Address = Inst.getPointerOperand(); 4006 Value *Val = Inst.getValueOperand(); 4007 Type *ElementType = Val->getType(); 4008 enum MemoryAccess::AccessType Type = 4009 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; 4010 4011 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); 4012 const SCEVUnknown *BasePointer = 4013 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction)); 4014 4015 assert(BasePointer && "Could not find base pointer"); 4016 AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer); 4017 4018 // Check if the access depends on a loop contained in a non-affine subregion. 4019 bool isVariantInNonAffineLoop = false; 4020 if (BoxedLoops) { 4021 SetVector<const Loop *> Loops; 4022 findLoops(AccessFunction, Loops); 4023 for (const Loop *L : Loops) 4024 if (BoxedLoops->count(L)) 4025 isVariantInNonAffineLoop = true; 4026 } 4027 4028 InvariantLoadsSetTy AccessILS; 4029 bool IsAffine = 4030 !isVariantInNonAffineLoop && 4031 isAffineExpr(R, AccessFunction, *SE, BasePointer->getValue(), &AccessILS); 4032 4033 for (LoadInst *LInst : AccessILS) 4034 if (!ScopRIL.count(LInst)) 4035 IsAffine = false; 4036 4037 if (!IsAffine && Type == MemoryAccess::MUST_WRITE) 4038 Type = MemoryAccess::MAY_WRITE; 4039 4040 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementType, IsAffine, 4041 {AccessFunction}, {}, Val); 4042 } 4043 4044 void ScopInfo::buildMemoryAccess( 4045 MemAccInst Inst, Loop *L, Region *R, 4046 const ScopDetection::BoxedLoopsSetTy *BoxedLoops, 4047 const InvariantLoadsSetTy &ScopRIL, const MapInsnToMemAcc &InsnToMemAcc) { 4048 4049 if (buildAccessMemIntrinsic(Inst, L, R, BoxedLoops, ScopRIL)) 4050 return; 4051 4052 if (buildAccessCallInst(Inst, L, R, BoxedLoops, ScopRIL)) 4053 return; 4054 4055 if (buildAccessMultiDimFixed(Inst, L, R, BoxedLoops, ScopRIL)) 4056 return; 4057 4058 if (buildAccessMultiDimParam(Inst, L, R, BoxedLoops, ScopRIL, InsnToMemAcc)) 4059 return; 4060 4061 buildAccessSingleDim(Inst, L, R, BoxedLoops, ScopRIL); 4062 } 4063 4064 void ScopInfo::buildAccessFunctions(Region &R, Region &SR, 4065 const MapInsnToMemAcc &InsnToMemAcc) { 4066 4067 if (SD->isNonAffineSubRegion(&SR, &R)) { 4068 for (BasicBlock *BB : SR.blocks()) 4069 buildAccessFunctions(R, *BB, InsnToMemAcc, &SR); 4070 return; 4071 } 4072 4073 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I) 4074 if (I->isSubRegion()) 4075 buildAccessFunctions(R, *I->getNodeAs<Region>(), InsnToMemAcc); 4076 else 4077 buildAccessFunctions(R, *I->getNodeAs<BasicBlock>(), InsnToMemAcc); 4078 } 4079 4080 void ScopInfo::buildStmts(Region &R, Region &SR) { 4081 4082 if (SD->isNonAffineSubRegion(&SR, &R)) { 4083 scop->addScopStmt(nullptr, &SR); 4084 return; 4085 } 4086 4087 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I) 4088 if (I->isSubRegion()) 4089 buildStmts(R, *I->getNodeAs<Region>()); 4090 else 4091 scop->addScopStmt(I->getNodeAs<BasicBlock>(), nullptr); 4092 } 4093 4094 void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB, 4095 const MapInsnToMemAcc &InsnToMemAcc, 4096 Region *NonAffineSubRegion, 4097 bool IsExitBlock) { 4098 // We do not build access functions for error blocks, as they may contain 4099 // instructions we can not model. 4100 if (isErrorBlock(BB, R, *LI, *DT) && !IsExitBlock) 4101 return; 4102 4103 Loop *L = LI->getLoopFor(&BB); 4104 4105 // The set of loops contained in non-affine subregions that are part of R. 4106 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD->getBoxedLoops(&R); 4107 4108 // The set of loads that are required to be invariant. 4109 auto &ScopRIL = *SD->getRequiredInvariantLoads(&R); 4110 4111 for (Instruction &Inst : BB) { 4112 PHINode *PHI = dyn_cast<PHINode>(&Inst); 4113 if (PHI) 4114 buildPHIAccesses(PHI, R, NonAffineSubRegion, IsExitBlock); 4115 4116 // For the exit block we stop modeling after the last PHI node. 4117 if (!PHI && IsExitBlock) 4118 break; 4119 4120 // TODO: At this point we only know that elements of ScopRIL have to be 4121 // invariant and will be hoisted for the SCoP to be processed. Though, 4122 // there might be other invariant accesses that will be hoisted and 4123 // that would allow to make a non-affine access affine. 4124 if (auto MemInst = MemAccInst::dyn_cast(Inst)) 4125 buildMemoryAccess(MemInst, L, &R, BoxedLoops, ScopRIL, InsnToMemAcc); 4126 4127 if (isIgnoredIntrinsic(&Inst)) 4128 continue; 4129 4130 if (!PHI) 4131 buildScalarDependences(&Inst); 4132 if (!IsExitBlock) 4133 buildEscapingDependences(&Inst); 4134 } 4135 } 4136 4137 MemoryAccess *ScopInfo::addMemoryAccess(BasicBlock *BB, Instruction *Inst, 4138 MemoryAccess::AccessType AccType, 4139 Value *BaseAddress, Type *ElementType, 4140 bool Affine, Value *AccessValue, 4141 ArrayRef<const SCEV *> Subscripts, 4142 ArrayRef<const SCEV *> Sizes, 4143 ScopArrayInfo::MemoryKind Kind) { 4144 ScopStmt *Stmt = scop->getStmtFor(BB); 4145 4146 // Do not create a memory access for anything not in the SCoP. It would be 4147 // ignored anyway. 4148 if (!Stmt) 4149 return nullptr; 4150 4151 AccFuncSetType &AccList = scop->getOrCreateAccessFunctions(BB); 4152 Value *BaseAddr = BaseAddress; 4153 std::string BaseName = getIslCompatibleName("MemRef_", BaseAddr, ""); 4154 4155 bool isKnownMustAccess = false; 4156 4157 // Accesses in single-basic block statements are always excuted. 4158 if (Stmt->isBlockStmt()) 4159 isKnownMustAccess = true; 4160 4161 if (Stmt->isRegionStmt()) { 4162 // Accesses that dominate the exit block of a non-affine region are always 4163 // executed. In non-affine regions there may exist MK_Values that do not 4164 // dominate the exit. MK_Values will always dominate the exit and MK_PHIs 4165 // only if there is at most one PHI_WRITE in the non-affine region. 4166 if (DT->dominates(BB, Stmt->getRegion()->getExit())) 4167 isKnownMustAccess = true; 4168 } 4169 4170 // Non-affine PHI writes do not "happen" at a particular instruction, but 4171 // after exiting the statement. Therefore they are guaranteed execute and 4172 // overwrite the old value. 4173 if (Kind == ScopArrayInfo::MK_PHI || Kind == ScopArrayInfo::MK_ExitPHI) 4174 isKnownMustAccess = true; 4175 4176 if (!isKnownMustAccess && AccType == MemoryAccess::MUST_WRITE) 4177 AccType = MemoryAccess::MAY_WRITE; 4178 4179 AccList.emplace_back(Stmt, Inst, AccType, BaseAddress, ElementType, Affine, 4180 Subscripts, Sizes, AccessValue, Kind, BaseName); 4181 Stmt->addAccess(&AccList.back()); 4182 return &AccList.back(); 4183 } 4184 4185 void ScopInfo::addArrayAccess(MemAccInst MemAccInst, 4186 MemoryAccess::AccessType AccType, 4187 Value *BaseAddress, Type *ElementType, 4188 bool IsAffine, ArrayRef<const SCEV *> Subscripts, 4189 ArrayRef<const SCEV *> Sizes, 4190 Value *AccessValue) { 4191 ArrayBasePointers.insert(BaseAddress); 4192 addMemoryAccess(MemAccInst->getParent(), MemAccInst, AccType, BaseAddress, 4193 ElementType, IsAffine, AccessValue, Subscripts, Sizes, 4194 ScopArrayInfo::MK_Array); 4195 } 4196 4197 void ScopInfo::ensureValueWrite(Instruction *Inst) { 4198 ScopStmt *Stmt = scop->getStmtFor(Inst); 4199 4200 // Inst not defined within this SCoP. 4201 if (!Stmt) 4202 return; 4203 4204 // Do not process further if the instruction is already written. 4205 if (Stmt->lookupValueWriteOf(Inst)) 4206 return; 4207 4208 addMemoryAccess(Inst->getParent(), Inst, MemoryAccess::MUST_WRITE, Inst, 4209 Inst->getType(), true, Inst, ArrayRef<const SCEV *>(), 4210 ArrayRef<const SCEV *>(), ScopArrayInfo::MK_Value); 4211 } 4212 4213 void ScopInfo::ensureValueRead(Value *V, BasicBlock *UserBB) { 4214 4215 // There cannot be an "access" for literal constants. BasicBlock references 4216 // (jump destinations) also never change. 4217 if ((isa<Constant>(V) && !isa<GlobalVariable>(V)) || isa<BasicBlock>(V)) 4218 return; 4219 4220 // If the instruction can be synthesized and the user is in the region we do 4221 // not need to add a value dependences. 4222 Region &ScopRegion = scop->getRegion(); 4223 auto *Scope = LI->getLoopFor(UserBB); 4224 if (canSynthesize(V, LI, SE, &ScopRegion, Scope)) 4225 return; 4226 4227 // Do not build scalar dependences for required invariant loads as we will 4228 // hoist them later on anyway or drop the SCoP if we cannot. 4229 auto *ScopRIL = SD->getRequiredInvariantLoads(&ScopRegion); 4230 if (ScopRIL->count(dyn_cast<LoadInst>(V))) 4231 return; 4232 4233 // Determine the ScopStmt containing the value's definition and use. There is 4234 // no defining ScopStmt if the value is a function argument, a global value, 4235 // or defined outside the SCoP. 4236 Instruction *ValueInst = dyn_cast<Instruction>(V); 4237 ScopStmt *ValueStmt = ValueInst ? scop->getStmtFor(ValueInst) : nullptr; 4238 4239 ScopStmt *UserStmt = scop->getStmtFor(UserBB); 4240 4241 // We do not model uses outside the scop. 4242 if (!UserStmt) 4243 return; 4244 4245 // Add MemoryAccess for invariant values only if requested. 4246 if (!ModelReadOnlyScalars && !ValueStmt) 4247 return; 4248 4249 // Ignore use-def chains within the same ScopStmt. 4250 if (ValueStmt == UserStmt) 4251 return; 4252 4253 // Do not create another MemoryAccess for reloading the value if one already 4254 // exists. 4255 if (UserStmt->lookupValueReadOf(V)) 4256 return; 4257 4258 addMemoryAccess(UserBB, nullptr, MemoryAccess::READ, V, V->getType(), true, V, 4259 ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(), 4260 ScopArrayInfo::MK_Value); 4261 if (ValueInst) 4262 ensureValueWrite(ValueInst); 4263 } 4264 4265 void ScopInfo::ensurePHIWrite(PHINode *PHI, BasicBlock *IncomingBlock, 4266 Value *IncomingValue, bool IsExitBlock) { 4267 ScopStmt *IncomingStmt = scop->getStmtFor(IncomingBlock); 4268 if (!IncomingStmt) 4269 return; 4270 4271 // Take care for the incoming value being available in the incoming block. 4272 // This must be done before the check for multiple PHI writes because multiple 4273 // exiting edges from subregion each can be the effective written value of the 4274 // subregion. As such, all of them must be made available in the subregion 4275 // statement. 4276 ensureValueRead(IncomingValue, IncomingBlock); 4277 4278 // Do not add more than one MemoryAccess per PHINode and ScopStmt. 4279 if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) { 4280 assert(Acc->getAccessInstruction() == PHI); 4281 Acc->addIncoming(IncomingBlock, IncomingValue); 4282 return; 4283 } 4284 4285 MemoryAccess *Acc = addMemoryAccess( 4286 IncomingStmt->getEntryBlock(), PHI, MemoryAccess::MUST_WRITE, PHI, 4287 PHI->getType(), true, PHI, ArrayRef<const SCEV *>(), 4288 ArrayRef<const SCEV *>(), 4289 IsExitBlock ? ScopArrayInfo::MK_ExitPHI : ScopArrayInfo::MK_PHI); 4290 assert(Acc); 4291 Acc->addIncoming(IncomingBlock, IncomingValue); 4292 } 4293 4294 void ScopInfo::addPHIReadAccess(PHINode *PHI) { 4295 addMemoryAccess(PHI->getParent(), PHI, MemoryAccess::READ, PHI, 4296 PHI->getType(), true, PHI, ArrayRef<const SCEV *>(), 4297 ArrayRef<const SCEV *>(), ScopArrayInfo::MK_PHI); 4298 } 4299 4300 void ScopInfo::buildScop(Region &R, AssumptionCache &AC) { 4301 unsigned MaxLoopDepth = getMaxLoopDepthInRegion(R, *LI, *SD); 4302 scop.reset(new Scop(R, *SE, MaxLoopDepth)); 4303 4304 buildStmts(R, R); 4305 buildAccessFunctions(R, R, *SD->getInsnToMemAccMap(&R)); 4306 4307 // In case the region does not have an exiting block we will later (during 4308 // code generation) split the exit block. This will move potential PHI nodes 4309 // from the current exit block into the new region exiting block. Hence, PHI 4310 // nodes that are at this point not part of the region will be. 4311 // To handle these PHI nodes later we will now model their operands as scalar 4312 // accesses. Note that we do not model anything in the exit block if we have 4313 // an exiting block in the region, as there will not be any splitting later. 4314 if (!R.getExitingBlock()) 4315 buildAccessFunctions(R, *R.getExit(), *SD->getInsnToMemAccMap(&R), nullptr, 4316 /* IsExitBlock */ true); 4317 4318 // Create memory accesses for global reads since all arrays are now known. 4319 auto *AF = SE->getConstant(IntegerType::getInt64Ty(SE->getContext()), 0); 4320 for (auto *GlobalRead : GlobalReads) 4321 for (auto *BP : ArrayBasePointers) 4322 addArrayAccess(MemAccInst(GlobalRead), MemoryAccess::READ, BP, 4323 BP->getType(), false, {AF}, {}, GlobalRead); 4324 4325 scop->init(*AA, AC, *SD, *DT, *LI); 4326 } 4327 4328 void ScopInfo::print(raw_ostream &OS, const Module *) const { 4329 if (!scop) { 4330 OS << "Invalid Scop!\n"; 4331 return; 4332 } 4333 4334 scop->print(OS); 4335 } 4336 4337 void ScopInfo::clear() { scop.reset(); } 4338 4339 //===----------------------------------------------------------------------===// 4340 ScopInfo::ScopInfo() : RegionPass(ID) {} 4341 4342 ScopInfo::~ScopInfo() { clear(); } 4343 4344 void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const { 4345 AU.addRequired<LoopInfoWrapperPass>(); 4346 AU.addRequired<RegionInfoPass>(); 4347 AU.addRequired<DominatorTreeWrapperPass>(); 4348 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 4349 AU.addRequiredTransitive<ScopDetection>(); 4350 AU.addRequired<AAResultsWrapperPass>(); 4351 AU.addRequired<AssumptionCacheTracker>(); 4352 AU.setPreservesAll(); 4353 } 4354 4355 bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) { 4356 SD = &getAnalysis<ScopDetection>(); 4357 4358 if (!SD->isMaxRegionInScop(*R)) 4359 return false; 4360 4361 Function *F = R->getEntry()->getParent(); 4362 SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 4363 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 4364 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); 4365 DL = &F->getParent()->getDataLayout(); 4366 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 4367 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F); 4368 4369 DebugLoc Beg, End; 4370 getDebugLocations(R, Beg, End); 4371 std::string Msg = "SCoP begins here."; 4372 emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, Beg, Msg); 4373 4374 buildScop(*R, AC); 4375 4376 DEBUG(scop->print(dbgs())); 4377 4378 if (scop->isEmpty() || !scop->hasFeasibleRuntimeContext()) { 4379 Msg = "SCoP ends here but was dismissed."; 4380 scop.reset(); 4381 } else { 4382 Msg = "SCoP ends here."; 4383 ++ScopFound; 4384 if (scop->getMaxLoopDepth() > 0) 4385 ++RichScopFound; 4386 } 4387 4388 emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, End, Msg); 4389 4390 return false; 4391 } 4392 4393 char ScopInfo::ID = 0; 4394 4395 Pass *polly::createScopInfoPass() { return new ScopInfo(); } 4396 4397 INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops", 4398 "Polly - Create polyhedral description of Scops", false, 4399 false); 4400 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); 4401 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); 4402 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 4403 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 4404 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 4405 INITIALIZE_PASS_DEPENDENCY(ScopDetection); 4406 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 4407 INITIALIZE_PASS_END(ScopInfo, "polly-scops", 4408 "Polly - Create polyhedral description of Scops", false, 4409 false) 4410