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