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