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