1 //===- ScopInfo.cpp -------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Create a polyhedral description for a static control flow region. 10 // 11 // The pass creates a polyhedral description of the Scops detected by the Scop 12 // detection derived from their LLVM-IR code. 13 // 14 // This representation is shared among several tools in the polyhedral 15 // community, which are e.g. Cloog, Pluto, Loopo, Graphite. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #include "polly/ScopInfo.h" 20 #include "polly/LinkAllPasses.h" 21 #include "polly/Options.h" 22 #include "polly/ScopBuilder.h" 23 #include "polly/ScopDetection.h" 24 #include "polly/Support/GICHelper.h" 25 #include "polly/Support/ISLOStream.h" 26 #include "polly/Support/ISLTools.h" 27 #include "polly/Support/SCEVAffinator.h" 28 #include "polly/Support/SCEVValidator.h" 29 #include "polly/Support/ScopHelper.h" 30 #include "llvm/ADT/APInt.h" 31 #include "llvm/ADT/ArrayRef.h" 32 #include "llvm/ADT/PostOrderIterator.h" 33 #include "llvm/ADT/SmallPtrSet.h" 34 #include "llvm/ADT/SmallSet.h" 35 #include "llvm/ADT/Statistic.h" 36 #include "llvm/Analysis/AliasAnalysis.h" 37 #include "llvm/Analysis/AssumptionCache.h" 38 #include "llvm/Analysis/Loads.h" 39 #include "llvm/Analysis/LoopInfo.h" 40 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 41 #include "llvm/Analysis/RegionInfo.h" 42 #include "llvm/Analysis/RegionIterator.h" 43 #include "llvm/Analysis/ScalarEvolution.h" 44 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 45 #include "llvm/IR/BasicBlock.h" 46 #include "llvm/IR/ConstantRange.h" 47 #include "llvm/IR/DataLayout.h" 48 #include "llvm/IR/DebugLoc.h" 49 #include "llvm/IR/Dominators.h" 50 #include "llvm/IR/Function.h" 51 #include "llvm/IR/InstrTypes.h" 52 #include "llvm/IR/Instruction.h" 53 #include "llvm/IR/Instructions.h" 54 #include "llvm/IR/Module.h" 55 #include "llvm/IR/PassManager.h" 56 #include "llvm/IR/Type.h" 57 #include "llvm/IR/Value.h" 58 #include "llvm/Support/Compiler.h" 59 #include "llvm/Support/Debug.h" 60 #include "llvm/Support/ErrorHandling.h" 61 #include "llvm/Support/raw_ostream.h" 62 #include "isl/aff.h" 63 #include "isl/local_space.h" 64 #include "isl/map.h" 65 #include "isl/options.h" 66 #include "isl/set.h" 67 #include <cassert> 68 69 using namespace llvm; 70 using namespace polly; 71 72 #define DEBUG_TYPE "polly-scops" 73 74 STATISTIC(AssumptionsAliasing, "Number of aliasing assumptions taken."); 75 STATISTIC(AssumptionsInbounds, "Number of inbounds assumptions taken."); 76 STATISTIC(AssumptionsWrapping, "Number of wrapping assumptions taken."); 77 STATISTIC(AssumptionsUnsigned, "Number of unsigned assumptions taken."); 78 STATISTIC(AssumptionsComplexity, "Number of too complex SCoPs."); 79 STATISTIC(AssumptionsUnprofitable, "Number of unprofitable SCoPs."); 80 STATISTIC(AssumptionsErrorBlock, "Number of error block assumptions taken."); 81 STATISTIC(AssumptionsInfiniteLoop, "Number of bounded loop assumptions taken."); 82 STATISTIC(AssumptionsInvariantLoad, 83 "Number of invariant loads assumptions taken."); 84 STATISTIC(AssumptionsDelinearization, 85 "Number of delinearization assumptions taken."); 86 87 STATISTIC(NumScops, "Number of feasible SCoPs after ScopInfo"); 88 STATISTIC(NumLoopsInScop, "Number of loops in scops"); 89 STATISTIC(NumBoxedLoops, "Number of boxed loops in SCoPs after ScopInfo"); 90 STATISTIC(NumAffineLoops, "Number of affine loops in SCoPs after ScopInfo"); 91 92 STATISTIC(NumScopsDepthZero, "Number of scops with maximal loop depth 0"); 93 STATISTIC(NumScopsDepthOne, "Number of scops with maximal loop depth 1"); 94 STATISTIC(NumScopsDepthTwo, "Number of scops with maximal loop depth 2"); 95 STATISTIC(NumScopsDepthThree, "Number of scops with maximal loop depth 3"); 96 STATISTIC(NumScopsDepthFour, "Number of scops with maximal loop depth 4"); 97 STATISTIC(NumScopsDepthFive, "Number of scops with maximal loop depth 5"); 98 STATISTIC(NumScopsDepthLarger, 99 "Number of scops with maximal loop depth 6 and larger"); 100 STATISTIC(MaxNumLoopsInScop, "Maximal number of loops in scops"); 101 102 STATISTIC(NumValueWrites, "Number of scalar value writes after ScopInfo"); 103 STATISTIC( 104 NumValueWritesInLoops, 105 "Number of scalar value writes nested in affine loops after ScopInfo"); 106 STATISTIC(NumPHIWrites, "Number of scalar phi writes after ScopInfo"); 107 STATISTIC(NumPHIWritesInLoops, 108 "Number of scalar phi writes nested in affine loops after ScopInfo"); 109 STATISTIC(NumSingletonWrites, "Number of singleton writes after ScopInfo"); 110 STATISTIC(NumSingletonWritesInLoops, 111 "Number of singleton writes nested in affine loops after ScopInfo"); 112 113 // The maximal number of basic sets we allow during domain construction to 114 // be created. More complex scops will result in very high compile time and 115 // are also unlikely to result in good code 116 static int const MaxDisjunctsInDomain = 20; 117 118 // The number of disjunct in the context after which we stop to add more 119 // disjuncts. This parameter is there to avoid exponential growth in the 120 // number of disjunct when adding non-convex sets to the context. 121 static int const MaxDisjunctsInContext = 4; 122 123 // The maximal number of dimensions we allow during invariant load construction. 124 // More complex access ranges will result in very high compile time and are also 125 // unlikely to result in good code. This value is very high and should only 126 // trigger for corner cases (e.g., the "dct_luma" function in h264, SPEC2006). 127 static int const MaxDimensionsInAccessRange = 9; 128 129 static cl::opt<int> 130 OptComputeOut("polly-analysis-computeout", 131 cl::desc("Bound the scop analysis by a maximal amount of " 132 "computational steps (0 means no bound)"), 133 cl::Hidden, cl::init(800000), cl::ZeroOrMore, 134 cl::cat(PollyCategory)); 135 136 static cl::opt<bool> PollyRemarksMinimal( 137 "polly-remarks-minimal", 138 cl::desc("Do not emit remarks about assumptions that are known"), 139 cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); 140 141 static cl::opt<int> RunTimeChecksMaxAccessDisjuncts( 142 "polly-rtc-max-array-disjuncts", 143 cl::desc("The maximal number of disjunts allowed in memory accesses to " 144 "to build RTCs."), 145 cl::Hidden, cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory)); 146 147 static cl::opt<unsigned> RunTimeChecksMaxParameters( 148 "polly-rtc-max-parameters", 149 cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden, 150 cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory)); 151 152 static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup( 153 "polly-rtc-max-arrays-per-group", 154 cl::desc("The maximal number of arrays to compare in each alias group."), 155 cl::Hidden, cl::ZeroOrMore, cl::init(20), cl::cat(PollyCategory)); 156 157 static cl::opt<std::string> UserContextStr( 158 "polly-context", cl::value_desc("isl parameter set"), 159 cl::desc("Provide additional constraints on the context parameters"), 160 cl::init(""), cl::cat(PollyCategory)); 161 162 static cl::opt<bool> 163 IslOnErrorAbort("polly-on-isl-error-abort", 164 cl::desc("Abort if an isl error is encountered"), 165 cl::init(true), cl::cat(PollyCategory)); 166 167 static cl::opt<bool> PollyPreciseInbounds( 168 "polly-precise-inbounds", 169 cl::desc("Take more precise inbounds assumptions (do not scale well)"), 170 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 171 172 static cl::opt<bool> 173 PollyIgnoreInbounds("polly-ignore-inbounds", 174 cl::desc("Do not take inbounds assumptions at all"), 175 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 176 177 static cl::opt<bool> PollyIgnoreParamBounds( 178 "polly-ignore-parameter-bounds", 179 cl::desc( 180 "Do not add parameter bounds and do no gist simplify sets accordingly"), 181 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 182 183 static cl::opt<bool> PollyAllowDereferenceOfAllFunctionParams( 184 "polly-allow-dereference-of-all-function-parameters", 185 cl::desc( 186 "Treat all parameters to functions that are pointers as dereferencible." 187 " This is useful for invariant load hoisting, since we can generate" 188 " less runtime checks. This is only valid if all pointers to functions" 189 " are always initialized, so that Polly can choose to hoist" 190 " their loads. "), 191 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 192 193 static cl::opt<bool> PollyPreciseFoldAccesses( 194 "polly-precise-fold-accesses", 195 cl::desc("Fold memory accesses to model more possible delinearizations " 196 "(does not scale well)"), 197 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 198 199 bool polly::UseInstructionNames; 200 201 static cl::opt<bool, true> XUseInstructionNames( 202 "polly-use-llvm-names", 203 cl::desc("Use LLVM-IR names when deriving statement names"), 204 cl::location(UseInstructionNames), cl::Hidden, cl::init(false), 205 cl::ZeroOrMore, cl::cat(PollyCategory)); 206 207 static cl::opt<bool> PollyPrintInstructions( 208 "polly-print-instructions", cl::desc("Output instructions per ScopStmt"), 209 cl::Hidden, cl::Optional, cl::init(false), cl::cat(PollyCategory)); 210 211 //===----------------------------------------------------------------------===// 212 213 // Create a sequence of two schedules. Either argument may be null and is 214 // interpreted as the empty schedule. Can also return null if both schedules are 215 // empty. 216 static isl::schedule combineInSequence(isl::schedule Prev, isl::schedule Succ) { 217 if (!Prev) 218 return Succ; 219 if (!Succ) 220 return Prev; 221 222 return Prev.sequence(Succ); 223 } 224 225 static isl::set addRangeBoundsToSet(isl::set S, const ConstantRange &Range, 226 int dim, isl::dim type) { 227 isl::val V; 228 isl::ctx Ctx = S.get_ctx(); 229 230 // The upper and lower bound for a parameter value is derived either from 231 // the data type of the parameter or from the - possibly more restrictive - 232 // range metadata. 233 V = valFromAPInt(Ctx.get(), Range.getSignedMin(), true); 234 S = S.lower_bound_val(type, dim, V); 235 V = valFromAPInt(Ctx.get(), Range.getSignedMax(), true); 236 S = S.upper_bound_val(type, dim, V); 237 238 if (Range.isFullSet()) 239 return S; 240 241 if (S.n_basic_set() > MaxDisjunctsInContext) 242 return S; 243 244 // In case of signed wrapping, we can refine the set of valid values by 245 // excluding the part not covered by the wrapping range. 246 if (Range.isSignWrappedSet()) { 247 V = valFromAPInt(Ctx.get(), Range.getLower(), true); 248 isl::set SLB = S.lower_bound_val(type, dim, V); 249 250 V = valFromAPInt(Ctx.get(), Range.getUpper(), true); 251 V = V.sub_ui(1); 252 isl::set SUB = S.upper_bound_val(type, dim, V); 253 S = SLB.unite(SUB); 254 } 255 256 return S; 257 } 258 259 static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) { 260 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr); 261 if (!BasePtrLI) 262 return nullptr; 263 264 if (!S->contains(BasePtrLI)) 265 return nullptr; 266 267 ScalarEvolution &SE = *S->getSE(); 268 269 auto *OriginBaseSCEV = 270 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand())); 271 if (!OriginBaseSCEV) 272 return nullptr; 273 274 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV); 275 if (!OriginBaseSCEVUnknown) 276 return nullptr; 277 278 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(), 279 MemoryKind::Array); 280 } 281 282 ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl::ctx Ctx, 283 ArrayRef<const SCEV *> Sizes, MemoryKind Kind, 284 const DataLayout &DL, Scop *S, 285 const char *BaseName) 286 : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) { 287 std::string BasePtrName = 288 BaseName ? BaseName 289 : getIslCompatibleName("MemRef", BasePtr, S->getNextArrayIdx(), 290 Kind == MemoryKind::PHI ? "__phi" : "", 291 UseInstructionNames); 292 Id = isl::id::alloc(Ctx, BasePtrName, this); 293 294 updateSizes(Sizes); 295 296 if (!BasePtr || Kind != MemoryKind::Array) { 297 BasePtrOriginSAI = nullptr; 298 return; 299 } 300 301 BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr); 302 if (BasePtrOriginSAI) 303 const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this); 304 } 305 306 ScopArrayInfo::~ScopArrayInfo() = default; 307 308 isl::space ScopArrayInfo::getSpace() const { 309 auto Space = isl::space(Id.get_ctx(), 0, getNumberOfDimensions()); 310 Space = Space.set_tuple_id(isl::dim::set, Id); 311 return Space; 312 } 313 314 bool ScopArrayInfo::isReadOnly() { 315 isl::union_set WriteSet = S.getWrites().range(); 316 isl::space Space = getSpace(); 317 WriteSet = WriteSet.extract_set(Space); 318 319 return bool(WriteSet.is_empty()); 320 } 321 322 bool ScopArrayInfo::isCompatibleWith(const ScopArrayInfo *Array) const { 323 if (Array->getElementType() != getElementType()) 324 return false; 325 326 if (Array->getNumberOfDimensions() != getNumberOfDimensions()) 327 return false; 328 329 for (unsigned i = 0; i < getNumberOfDimensions(); i++) 330 if (Array->getDimensionSize(i) != getDimensionSize(i)) 331 return false; 332 333 return true; 334 } 335 336 void ScopArrayInfo::updateElementType(Type *NewElementType) { 337 if (NewElementType == ElementType) 338 return; 339 340 auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType); 341 auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType); 342 343 if (NewElementSize == OldElementSize || NewElementSize == 0) 344 return; 345 346 if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) { 347 ElementType = NewElementType; 348 } else { 349 auto GCD = GreatestCommonDivisor64(NewElementSize, OldElementSize); 350 ElementType = IntegerType::get(ElementType->getContext(), GCD); 351 } 352 } 353 354 /// Make the ScopArrayInfo model a Fortran Array 355 void ScopArrayInfo::applyAndSetFAD(Value *FAD) { 356 assert(FAD && "got invalid Fortran array descriptor"); 357 if (this->FAD) { 358 assert(this->FAD == FAD && 359 "receiving different array descriptors for same array"); 360 return; 361 } 362 363 assert(DimensionSizesPw.size() > 0 && !DimensionSizesPw[0]); 364 assert(!this->FAD); 365 this->FAD = FAD; 366 367 isl::space Space(S.getIslCtx(), 1, 0); 368 369 std::string param_name = getName(); 370 param_name += "_fortranarr_size"; 371 isl::id IdPwAff = isl::id::alloc(S.getIslCtx(), param_name, this); 372 373 Space = Space.set_dim_id(isl::dim::param, 0, IdPwAff); 374 isl::pw_aff PwAff = 375 isl::aff::var_on_domain(isl::local_space(Space), isl::dim::param, 0); 376 377 DimensionSizesPw[0] = PwAff; 378 } 379 380 bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes, 381 bool CheckConsistency) { 382 int SharedDims = std::min(NewSizes.size(), DimensionSizes.size()); 383 int ExtraDimsNew = NewSizes.size() - SharedDims; 384 int ExtraDimsOld = DimensionSizes.size() - SharedDims; 385 386 if (CheckConsistency) { 387 for (int i = 0; i < SharedDims; i++) { 388 auto *NewSize = NewSizes[i + ExtraDimsNew]; 389 auto *KnownSize = DimensionSizes[i + ExtraDimsOld]; 390 if (NewSize && KnownSize && NewSize != KnownSize) 391 return false; 392 } 393 394 if (DimensionSizes.size() >= NewSizes.size()) 395 return true; 396 } 397 398 DimensionSizes.clear(); 399 DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(), 400 NewSizes.end()); 401 DimensionSizesPw.clear(); 402 for (const SCEV *Expr : DimensionSizes) { 403 if (!Expr) { 404 DimensionSizesPw.push_back(nullptr); 405 continue; 406 } 407 isl::pw_aff Size = S.getPwAffOnly(Expr); 408 DimensionSizesPw.push_back(Size); 409 } 410 return true; 411 } 412 413 std::string ScopArrayInfo::getName() const { return Id.get_name(); } 414 415 int ScopArrayInfo::getElemSizeInBytes() const { 416 return DL.getTypeAllocSize(ElementType); 417 } 418 419 isl::id ScopArrayInfo::getBasePtrId() const { return Id; } 420 421 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 422 LLVM_DUMP_METHOD void ScopArrayInfo::dump() const { print(errs()); } 423 #endif 424 425 void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const { 426 OS.indent(8) << *getElementType() << " " << getName(); 427 unsigned u = 0; 428 // If this is a Fortran array, then we can print the outermost dimension 429 // as a isl_pw_aff even though there is no SCEV information. 430 bool IsOutermostSizeKnown = SizeAsPwAff && FAD; 431 432 if (!IsOutermostSizeKnown && getNumberOfDimensions() > 0 && 433 !getDimensionSize(0)) { 434 OS << "[*]"; 435 u++; 436 } 437 for (; u < getNumberOfDimensions(); u++) { 438 OS << "["; 439 440 if (SizeAsPwAff) { 441 isl::pw_aff Size = getDimensionSizePw(u); 442 OS << " " << Size << " "; 443 } else { 444 OS << *getDimensionSize(u); 445 } 446 447 OS << "]"; 448 } 449 450 OS << ";"; 451 452 if (BasePtrOriginSAI) 453 OS << " [BasePtrOrigin: " << BasePtrOriginSAI->getName() << "]"; 454 455 OS << " // Element size " << getElemSizeInBytes() << "\n"; 456 } 457 458 const ScopArrayInfo * 459 ScopArrayInfo::getFromAccessFunction(isl::pw_multi_aff PMA) { 460 isl::id Id = PMA.get_tuple_id(isl::dim::out); 461 assert(!Id.is_null() && "Output dimension didn't have an ID"); 462 return getFromId(Id); 463 } 464 465 const ScopArrayInfo *ScopArrayInfo::getFromId(isl::id Id) { 466 void *User = Id.get_user(); 467 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 468 return SAI; 469 } 470 471 void MemoryAccess::wrapConstantDimensions() { 472 auto *SAI = getScopArrayInfo(); 473 isl::space ArraySpace = SAI->getSpace(); 474 isl::ctx Ctx = ArraySpace.get_ctx(); 475 unsigned DimsArray = SAI->getNumberOfDimensions(); 476 477 isl::multi_aff DivModAff = isl::multi_aff::identity( 478 ArraySpace.map_from_domain_and_range(ArraySpace)); 479 isl::local_space LArraySpace = isl::local_space(ArraySpace); 480 481 // Begin with last dimension, to iteratively carry into higher dimensions. 482 for (int i = DimsArray - 1; i > 0; i--) { 483 auto *DimSize = SAI->getDimensionSize(i); 484 auto *DimSizeCst = dyn_cast<SCEVConstant>(DimSize); 485 486 // This transformation is not applicable to dimensions with dynamic size. 487 if (!DimSizeCst) 488 continue; 489 490 // This transformation is not applicable to dimensions of size zero. 491 if (DimSize->isZero()) 492 continue; 493 494 isl::val DimSizeVal = 495 valFromAPInt(Ctx.get(), DimSizeCst->getAPInt(), false); 496 isl::aff Var = isl::aff::var_on_domain(LArraySpace, isl::dim::set, i); 497 isl::aff PrevVar = 498 isl::aff::var_on_domain(LArraySpace, isl::dim::set, i - 1); 499 500 // Compute: index % size 501 // Modulo must apply in the divide of the previous iteration, if any. 502 isl::aff Modulo = Var.mod(DimSizeVal); 503 Modulo = Modulo.pullback(DivModAff); 504 505 // Compute: floor(index / size) 506 isl::aff Divide = Var.div(isl::aff(LArraySpace, DimSizeVal)); 507 Divide = Divide.floor(); 508 Divide = Divide.add(PrevVar); 509 Divide = Divide.pullback(DivModAff); 510 511 // Apply Modulo and Divide. 512 DivModAff = DivModAff.set_aff(i, Modulo); 513 DivModAff = DivModAff.set_aff(i - 1, Divide); 514 } 515 516 // Apply all modulo/divides on the accesses. 517 isl::map Relation = AccessRelation; 518 Relation = Relation.apply_range(isl::map::from_multi_aff(DivModAff)); 519 Relation = Relation.detect_equalities(); 520 AccessRelation = Relation; 521 } 522 523 void MemoryAccess::updateDimensionality() { 524 auto *SAI = getScopArrayInfo(); 525 isl::space ArraySpace = SAI->getSpace(); 526 isl::space AccessSpace = AccessRelation.get_space().range(); 527 isl::ctx Ctx = ArraySpace.get_ctx(); 528 529 auto DimsArray = ArraySpace.dim(isl::dim::set); 530 auto DimsAccess = AccessSpace.dim(isl::dim::set); 531 auto DimsMissing = DimsArray - DimsAccess; 532 533 auto *BB = getStatement()->getEntryBlock(); 534 auto &DL = BB->getModule()->getDataLayout(); 535 unsigned ArrayElemSize = SAI->getElemSizeInBytes(); 536 unsigned ElemBytes = DL.getTypeAllocSize(getElementType()); 537 538 isl::map Map = isl::map::from_domain_and_range( 539 isl::set::universe(AccessSpace), isl::set::universe(ArraySpace)); 540 541 for (unsigned i = 0; i < DimsMissing; i++) 542 Map = Map.fix_si(isl::dim::out, i, 0); 543 544 for (unsigned i = DimsMissing; i < DimsArray; i++) 545 Map = Map.equate(isl::dim::in, i - DimsMissing, isl::dim::out, i); 546 547 AccessRelation = AccessRelation.apply_range(Map); 548 549 // For the non delinearized arrays, divide the access function of the last 550 // subscript by the size of the elements in the array. 551 // 552 // A stride one array access in C expressed as A[i] is expressed in 553 // LLVM-IR as something like A[i * elementsize]. This hides the fact that 554 // two subsequent values of 'i' index two values that are stored next to 555 // each other in memory. By this division we make this characteristic 556 // obvious again. If the base pointer was accessed with offsets not divisible 557 // by the accesses element size, we will have chosen a smaller ArrayElemSize 558 // that divides the offsets of all accesses to this base pointer. 559 if (DimsAccess == 1) { 560 isl::val V = isl::val(Ctx, ArrayElemSize); 561 AccessRelation = AccessRelation.floordiv_val(V); 562 } 563 564 // We currently do this only if we added at least one dimension, which means 565 // some dimension's indices have not been specified, an indicator that some 566 // index values have been added together. 567 // TODO: Investigate general usefulness; Effect on unit tests is to make index 568 // expressions more complicated. 569 if (DimsMissing) 570 wrapConstantDimensions(); 571 572 if (!isAffine()) 573 computeBoundsOnAccessRelation(ArrayElemSize); 574 575 // Introduce multi-element accesses in case the type loaded by this memory 576 // access is larger than the canonical element type of the array. 577 // 578 // An access ((float *)A)[i] to an array char *A is modeled as 579 // {[i] -> A[o] : 4 i <= o <= 4 i + 3 580 if (ElemBytes > ArrayElemSize) { 581 assert(ElemBytes % ArrayElemSize == 0 && 582 "Loaded element size should be multiple of canonical element size"); 583 isl::map Map = isl::map::from_domain_and_range( 584 isl::set::universe(ArraySpace), isl::set::universe(ArraySpace)); 585 for (unsigned i = 0; i < DimsArray - 1; i++) 586 Map = Map.equate(isl::dim::in, i, isl::dim::out, i); 587 588 isl::constraint C; 589 isl::local_space LS; 590 591 LS = isl::local_space(Map.get_space()); 592 int Num = ElemBytes / getScopArrayInfo()->getElemSizeInBytes(); 593 594 C = isl::constraint::alloc_inequality(LS); 595 C = C.set_constant_val(isl::val(Ctx, Num - 1)); 596 C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, 1); 597 C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, -1); 598 Map = Map.add_constraint(C); 599 600 C = isl::constraint::alloc_inequality(LS); 601 C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, -1); 602 C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, 1); 603 C = C.set_constant_val(isl::val(Ctx, 0)); 604 Map = Map.add_constraint(C); 605 AccessRelation = AccessRelation.apply_range(Map); 606 } 607 } 608 609 const std::string 610 MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) { 611 switch (RT) { 612 case MemoryAccess::RT_NONE: 613 llvm_unreachable("Requested a reduction operator string for a memory " 614 "access which isn't a reduction"); 615 case MemoryAccess::RT_ADD: 616 return "+"; 617 case MemoryAccess::RT_MUL: 618 return "*"; 619 case MemoryAccess::RT_BOR: 620 return "|"; 621 case MemoryAccess::RT_BXOR: 622 return "^"; 623 case MemoryAccess::RT_BAND: 624 return "&"; 625 } 626 llvm_unreachable("Unknown reduction type"); 627 } 628 629 const ScopArrayInfo *MemoryAccess::getOriginalScopArrayInfo() const { 630 isl::id ArrayId = getArrayId(); 631 void *User = ArrayId.get_user(); 632 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 633 return SAI; 634 } 635 636 const ScopArrayInfo *MemoryAccess::getLatestScopArrayInfo() const { 637 isl::id ArrayId = getLatestArrayId(); 638 void *User = ArrayId.get_user(); 639 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 640 return SAI; 641 } 642 643 isl::id MemoryAccess::getOriginalArrayId() const { 644 return AccessRelation.get_tuple_id(isl::dim::out); 645 } 646 647 isl::id MemoryAccess::getLatestArrayId() const { 648 if (!hasNewAccessRelation()) 649 return getOriginalArrayId(); 650 return NewAccessRelation.get_tuple_id(isl::dim::out); 651 } 652 653 isl::map MemoryAccess::getAddressFunction() const { 654 return getAccessRelation().lexmin(); 655 } 656 657 isl::pw_multi_aff 658 MemoryAccess::applyScheduleToAccessRelation(isl::union_map USchedule) const { 659 isl::map Schedule, ScheduledAccRel; 660 isl::union_set UDomain; 661 662 UDomain = getStatement()->getDomain(); 663 USchedule = USchedule.intersect_domain(UDomain); 664 Schedule = isl::map::from_union_map(USchedule); 665 ScheduledAccRel = getAddressFunction().apply_domain(Schedule); 666 return isl::pw_multi_aff::from_map(ScheduledAccRel); 667 } 668 669 isl::map MemoryAccess::getOriginalAccessRelation() const { 670 return AccessRelation; 671 } 672 673 std::string MemoryAccess::getOriginalAccessRelationStr() const { 674 return AccessRelation.to_str(); 675 } 676 677 isl::space MemoryAccess::getOriginalAccessRelationSpace() const { 678 return AccessRelation.get_space(); 679 } 680 681 isl::map MemoryAccess::getNewAccessRelation() const { 682 return NewAccessRelation; 683 } 684 685 std::string MemoryAccess::getNewAccessRelationStr() const { 686 return NewAccessRelation.to_str(); 687 } 688 689 std::string MemoryAccess::getAccessRelationStr() const { 690 return getAccessRelation().to_str(); 691 } 692 693 isl::basic_map MemoryAccess::createBasicAccessMap(ScopStmt *Statement) { 694 isl::space Space = isl::space(Statement->getIslCtx(), 0, 1); 695 Space = Space.align_params(Statement->getDomainSpace()); 696 697 return isl::basic_map::from_domain_and_range( 698 isl::basic_set::universe(Statement->getDomainSpace()), 699 isl::basic_set::universe(Space)); 700 } 701 702 // Formalize no out-of-bound access assumption 703 // 704 // When delinearizing array accesses we optimistically assume that the 705 // delinearized accesses do not access out of bound locations (the subscript 706 // expression of each array evaluates for each statement instance that is 707 // executed to a value that is larger than zero and strictly smaller than the 708 // size of the corresponding dimension). The only exception is the outermost 709 // dimension for which we do not need to assume any upper bound. At this point 710 // we formalize this assumption to ensure that at code generation time the 711 // relevant run-time checks can be generated. 712 // 713 // To find the set of constraints necessary to avoid out of bound accesses, we 714 // first build the set of data locations that are not within array bounds. We 715 // then apply the reverse access relation to obtain the set of iterations that 716 // may contain invalid accesses and reduce this set of iterations to the ones 717 // that are actually executed by intersecting them with the domain of the 718 // statement. If we now project out all loop dimensions, we obtain a set of 719 // parameters that may cause statement instances to be executed that may 720 // possibly yield out of bound memory accesses. The complement of these 721 // constraints is the set of constraints that needs to be assumed to ensure such 722 // statement instances are never executed. 723 void MemoryAccess::assumeNoOutOfBound() { 724 if (PollyIgnoreInbounds) 725 return; 726 auto *SAI = getScopArrayInfo(); 727 isl::space Space = getOriginalAccessRelationSpace().range(); 728 isl::set Outside = isl::set::empty(Space); 729 for (int i = 1, Size = Space.dim(isl::dim::set); i < Size; ++i) { 730 isl::local_space LS(Space); 731 isl::pw_aff Var = isl::pw_aff::var_on_domain(LS, isl::dim::set, i); 732 isl::pw_aff Zero = isl::pw_aff(LS); 733 734 isl::set DimOutside = Var.lt_set(Zero); 735 isl::pw_aff SizeE = SAI->getDimensionSizePw(i); 736 SizeE = SizeE.add_dims(isl::dim::in, Space.dim(isl::dim::set)); 737 SizeE = SizeE.set_tuple_id(isl::dim::in, Space.get_tuple_id(isl::dim::set)); 738 DimOutside = DimOutside.unite(SizeE.le_set(Var)); 739 740 Outside = Outside.unite(DimOutside); 741 } 742 743 Outside = Outside.apply(getAccessRelation().reverse()); 744 Outside = Outside.intersect(Statement->getDomain()); 745 Outside = Outside.params(); 746 747 // Remove divs to avoid the construction of overly complicated assumptions. 748 // Doing so increases the set of parameter combinations that are assumed to 749 // not appear. This is always save, but may make the resulting run-time check 750 // bail out more often than strictly necessary. 751 Outside = Outside.remove_divs(); 752 Outside = Outside.complement(); 753 const auto &Loc = getAccessInstruction() 754 ? getAccessInstruction()->getDebugLoc() 755 : DebugLoc(); 756 if (!PollyPreciseInbounds) 757 Outside = Outside.gist_params(Statement->getDomain().params()); 758 Statement->getParent()->recordAssumption(INBOUNDS, Outside, Loc, 759 AS_ASSUMPTION); 760 } 761 762 void MemoryAccess::buildMemIntrinsicAccessRelation() { 763 assert(isMemoryIntrinsic()); 764 assert(Subscripts.size() == 2 && Sizes.size() == 1); 765 766 isl::pw_aff SubscriptPWA = getPwAff(Subscripts[0]); 767 isl::map SubscriptMap = isl::map::from_pw_aff(SubscriptPWA); 768 769 isl::map LengthMap; 770 if (Subscripts[1] == nullptr) { 771 LengthMap = isl::map::universe(SubscriptMap.get_space()); 772 } else { 773 isl::pw_aff LengthPWA = getPwAff(Subscripts[1]); 774 LengthMap = isl::map::from_pw_aff(LengthPWA); 775 isl::space RangeSpace = LengthMap.get_space().range(); 776 LengthMap = LengthMap.apply_range(isl::map::lex_gt(RangeSpace)); 777 } 778 LengthMap = LengthMap.lower_bound_si(isl::dim::out, 0, 0); 779 LengthMap = LengthMap.align_params(SubscriptMap.get_space()); 780 SubscriptMap = SubscriptMap.align_params(LengthMap.get_space()); 781 LengthMap = LengthMap.sum(SubscriptMap); 782 AccessRelation = 783 LengthMap.set_tuple_id(isl::dim::in, getStatement()->getDomainId()); 784 } 785 786 void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) { 787 ScalarEvolution *SE = Statement->getParent()->getSE(); 788 789 auto MAI = MemAccInst(getAccessInstruction()); 790 if (isa<MemIntrinsic>(MAI)) 791 return; 792 793 Value *Ptr = MAI.getPointerOperand(); 794 if (!Ptr || !SE->isSCEVable(Ptr->getType())) 795 return; 796 797 auto *PtrSCEV = SE->getSCEV(Ptr); 798 if (isa<SCEVCouldNotCompute>(PtrSCEV)) 799 return; 800 801 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV); 802 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV)) 803 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV); 804 805 const ConstantRange &Range = SE->getSignedRange(PtrSCEV); 806 if (Range.isFullSet()) 807 return; 808 809 if (Range.isUpperWrapped() || Range.isSignWrappedSet()) 810 return; 811 812 bool isWrapping = Range.isSignWrappedSet(); 813 814 unsigned BW = Range.getBitWidth(); 815 const auto One = APInt(BW, 1); 816 const auto LB = isWrapping ? Range.getLower() : Range.getSignedMin(); 817 const auto UB = isWrapping ? (Range.getUpper() - One) : Range.getSignedMax(); 818 819 auto Min = LB.sdiv(APInt(BW, ElementSize)); 820 auto Max = UB.sdiv(APInt(BW, ElementSize)) + One; 821 822 assert(Min.sle(Max) && "Minimum expected to be less or equal than max"); 823 824 isl::map Relation = AccessRelation; 825 isl::set AccessRange = Relation.range(); 826 AccessRange = addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0, 827 isl::dim::set); 828 AccessRelation = Relation.intersect_range(AccessRange); 829 } 830 831 void MemoryAccess::foldAccessRelation() { 832 if (Sizes.size() < 2 || isa<SCEVConstant>(Sizes[1])) 833 return; 834 835 int Size = Subscripts.size(); 836 837 isl::map NewAccessRelation = AccessRelation; 838 839 for (int i = Size - 2; i >= 0; --i) { 840 isl::space Space; 841 isl::map MapOne, MapTwo; 842 isl::pw_aff DimSize = getPwAff(Sizes[i + 1]); 843 844 isl::space SpaceSize = DimSize.get_space(); 845 isl::id ParamId = SpaceSize.get_dim_id(isl::dim::param, 0); 846 847 Space = AccessRelation.get_space(); 848 Space = Space.range().map_from_set(); 849 Space = Space.align_params(SpaceSize); 850 851 int ParamLocation = Space.find_dim_by_id(isl::dim::param, ParamId); 852 853 MapOne = isl::map::universe(Space); 854 for (int j = 0; j < Size; ++j) 855 MapOne = MapOne.equate(isl::dim::in, j, isl::dim::out, j); 856 MapOne = MapOne.lower_bound_si(isl::dim::in, i + 1, 0); 857 858 MapTwo = isl::map::universe(Space); 859 for (int j = 0; j < Size; ++j) 860 if (j < i || j > i + 1) 861 MapTwo = MapTwo.equate(isl::dim::in, j, isl::dim::out, j); 862 863 isl::local_space LS(Space); 864 isl::constraint C; 865 C = isl::constraint::alloc_equality(LS); 866 C = C.set_constant_si(-1); 867 C = C.set_coefficient_si(isl::dim::in, i, 1); 868 C = C.set_coefficient_si(isl::dim::out, i, -1); 869 MapTwo = MapTwo.add_constraint(C); 870 C = isl::constraint::alloc_equality(LS); 871 C = C.set_coefficient_si(isl::dim::in, i + 1, 1); 872 C = C.set_coefficient_si(isl::dim::out, i + 1, -1); 873 C = C.set_coefficient_si(isl::dim::param, ParamLocation, 1); 874 MapTwo = MapTwo.add_constraint(C); 875 MapTwo = MapTwo.upper_bound_si(isl::dim::in, i + 1, -1); 876 877 MapOne = MapOne.unite(MapTwo); 878 NewAccessRelation = NewAccessRelation.apply_range(MapOne); 879 } 880 881 isl::id BaseAddrId = getScopArrayInfo()->getBasePtrId(); 882 isl::space Space = Statement->getDomainSpace(); 883 NewAccessRelation = NewAccessRelation.set_tuple_id( 884 isl::dim::in, Space.get_tuple_id(isl::dim::set)); 885 NewAccessRelation = NewAccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 886 NewAccessRelation = NewAccessRelation.gist_domain(Statement->getDomain()); 887 888 // Access dimension folding might in certain cases increase the number of 889 // disjuncts in the memory access, which can possibly complicate the generated 890 // run-time checks and can lead to costly compilation. 891 if (!PollyPreciseFoldAccesses && 892 NewAccessRelation.n_basic_map() > AccessRelation.n_basic_map()) { 893 } else { 894 AccessRelation = NewAccessRelation; 895 } 896 } 897 898 /// Check if @p Expr is divisible by @p Size. 899 static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) { 900 assert(Size != 0); 901 if (Size == 1) 902 return true; 903 904 // Only one factor needs to be divisible. 905 if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) { 906 for (auto *FactorExpr : MulExpr->operands()) 907 if (isDivisible(FactorExpr, Size, SE)) 908 return true; 909 return false; 910 } 911 912 // For other n-ary expressions (Add, AddRec, Max,...) all operands need 913 // to be divisible. 914 if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) { 915 for (auto *OpExpr : NAryExpr->operands()) 916 if (!isDivisible(OpExpr, Size, SE)) 917 return false; 918 return true; 919 } 920 921 auto *SizeSCEV = SE.getConstant(Expr->getType(), Size); 922 auto *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV); 923 auto *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV); 924 return MulSCEV == Expr; 925 } 926 927 void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) { 928 assert(AccessRelation.is_null() && "AccessRelation already built"); 929 930 // Initialize the invalid domain which describes all iterations for which the 931 // access relation is not modeled correctly. 932 isl::set StmtInvalidDomain = getStatement()->getInvalidDomain(); 933 InvalidDomain = isl::set::empty(StmtInvalidDomain.get_space()); 934 935 isl::ctx Ctx = Id.get_ctx(); 936 isl::id BaseAddrId = SAI->getBasePtrId(); 937 938 if (getAccessInstruction() && isa<MemIntrinsic>(getAccessInstruction())) { 939 buildMemIntrinsicAccessRelation(); 940 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 941 return; 942 } 943 944 if (!isAffine()) { 945 // We overapproximate non-affine accesses with a possible access to the 946 // whole array. For read accesses it does not make a difference, if an 947 // access must or may happen. However, for write accesses it is important to 948 // differentiate between writes that must happen and writes that may happen. 949 if (AccessRelation.is_null()) 950 AccessRelation = createBasicAccessMap(Statement); 951 952 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 953 return; 954 } 955 956 isl::space Space = isl::space(Ctx, 0, Statement->getNumIterators(), 0); 957 AccessRelation = isl::map::universe(Space); 958 959 for (int i = 0, Size = Subscripts.size(); i < Size; ++i) { 960 isl::pw_aff Affine = getPwAff(Subscripts[i]); 961 isl::map SubscriptMap = isl::map::from_pw_aff(Affine); 962 AccessRelation = AccessRelation.flat_range_product(SubscriptMap); 963 } 964 965 Space = Statement->getDomainSpace(); 966 AccessRelation = AccessRelation.set_tuple_id( 967 isl::dim::in, Space.get_tuple_id(isl::dim::set)); 968 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 969 970 AccessRelation = AccessRelation.gist_domain(Statement->getDomain()); 971 } 972 973 MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst, 974 AccessType AccType, Value *BaseAddress, 975 Type *ElementType, bool Affine, 976 ArrayRef<const SCEV *> Subscripts, 977 ArrayRef<const SCEV *> Sizes, Value *AccessValue, 978 MemoryKind Kind) 979 : Kind(Kind), AccType(AccType), Statement(Stmt), InvalidDomain(nullptr), 980 BaseAddr(BaseAddress), ElementType(ElementType), 981 Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst), 982 AccessValue(AccessValue), IsAffine(Affine), 983 Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(nullptr), 984 NewAccessRelation(nullptr), FAD(nullptr) { 985 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"}; 986 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size()); 987 988 std::string IdName = Stmt->getBaseName() + Access; 989 Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this); 990 } 991 992 MemoryAccess::MemoryAccess(ScopStmt *Stmt, AccessType AccType, isl::map AccRel) 993 : Kind(MemoryKind::Array), AccType(AccType), Statement(Stmt), 994 InvalidDomain(nullptr), AccessRelation(nullptr), 995 NewAccessRelation(AccRel), FAD(nullptr) { 996 isl::id ArrayInfoId = NewAccessRelation.get_tuple_id(isl::dim::out); 997 auto *SAI = ScopArrayInfo::getFromId(ArrayInfoId); 998 Sizes.push_back(nullptr); 999 for (unsigned i = 1; i < SAI->getNumberOfDimensions(); i++) 1000 Sizes.push_back(SAI->getDimensionSize(i)); 1001 ElementType = SAI->getElementType(); 1002 BaseAddr = SAI->getBasePtr(); 1003 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"}; 1004 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size()); 1005 1006 std::string IdName = Stmt->getBaseName() + Access; 1007 Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this); 1008 } 1009 1010 MemoryAccess::~MemoryAccess() = default; 1011 1012 void MemoryAccess::realignParams() { 1013 isl::set Ctx = Statement->getParent()->getContext(); 1014 InvalidDomain = InvalidDomain.gist_params(Ctx); 1015 AccessRelation = AccessRelation.gist_params(Ctx); 1016 } 1017 1018 const std::string MemoryAccess::getReductionOperatorStr() const { 1019 return MemoryAccess::getReductionOperatorStr(getReductionType()); 1020 } 1021 1022 isl::id MemoryAccess::getId() const { return Id; } 1023 1024 raw_ostream &polly::operator<<(raw_ostream &OS, 1025 MemoryAccess::ReductionType RT) { 1026 if (RT == MemoryAccess::RT_NONE) 1027 OS << "NONE"; 1028 else 1029 OS << MemoryAccess::getReductionOperatorStr(RT); 1030 return OS; 1031 } 1032 1033 void MemoryAccess::setFortranArrayDescriptor(Value *FAD) { this->FAD = FAD; } 1034 1035 void MemoryAccess::print(raw_ostream &OS) const { 1036 switch (AccType) { 1037 case READ: 1038 OS.indent(12) << "ReadAccess :=\t"; 1039 break; 1040 case MUST_WRITE: 1041 OS.indent(12) << "MustWriteAccess :=\t"; 1042 break; 1043 case MAY_WRITE: 1044 OS.indent(12) << "MayWriteAccess :=\t"; 1045 break; 1046 } 1047 1048 OS << "[Reduction Type: " << getReductionType() << "] "; 1049 1050 if (FAD) { 1051 OS << "[Fortran array descriptor: " << FAD->getName(); 1052 OS << "] "; 1053 }; 1054 1055 OS << "[Scalar: " << isScalarKind() << "]\n"; 1056 OS.indent(16) << getOriginalAccessRelationStr() << ";\n"; 1057 if (hasNewAccessRelation()) 1058 OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n"; 1059 } 1060 1061 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1062 LLVM_DUMP_METHOD void MemoryAccess::dump() const { print(errs()); } 1063 #endif 1064 1065 isl::pw_aff MemoryAccess::getPwAff(const SCEV *E) { 1066 auto *Stmt = getStatement(); 1067 PWACtx PWAC = Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock()); 1068 isl::set StmtDom = getStatement()->getDomain(); 1069 StmtDom = StmtDom.reset_tuple_id(); 1070 isl::set NewInvalidDom = StmtDom.intersect(PWAC.second); 1071 InvalidDomain = InvalidDomain.unite(NewInvalidDom); 1072 return PWAC.first; 1073 } 1074 1075 // Create a map in the size of the provided set domain, that maps from the 1076 // one element of the provided set domain to another element of the provided 1077 // set domain. 1078 // The mapping is limited to all points that are equal in all but the last 1079 // dimension and for which the last dimension of the input is strict smaller 1080 // than the last dimension of the output. 1081 // 1082 // getEqualAndLarger(set[i0, i1, ..., iX]): 1083 // 1084 // set[i0, i1, ..., iX] -> set[o0, o1, ..., oX] 1085 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX 1086 // 1087 static isl::map getEqualAndLarger(isl::space SetDomain) { 1088 isl::space Space = SetDomain.map_from_set(); 1089 isl::map Map = isl::map::universe(Space); 1090 unsigned lastDimension = Map.dim(isl::dim::in) - 1; 1091 1092 // Set all but the last dimension to be equal for the input and output 1093 // 1094 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX] 1095 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1) 1096 for (unsigned i = 0; i < lastDimension; ++i) 1097 Map = Map.equate(isl::dim::in, i, isl::dim::out, i); 1098 1099 // Set the last dimension of the input to be strict smaller than the 1100 // last dimension of the output. 1101 // 1102 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX 1103 Map = Map.order_lt(isl::dim::in, lastDimension, isl::dim::out, lastDimension); 1104 return Map; 1105 } 1106 1107 isl::set MemoryAccess::getStride(isl::map Schedule) const { 1108 isl::map AccessRelation = getAccessRelation(); 1109 isl::space Space = Schedule.get_space().range(); 1110 isl::map NextScatt = getEqualAndLarger(Space); 1111 1112 Schedule = Schedule.reverse(); 1113 NextScatt = NextScatt.lexmin(); 1114 1115 NextScatt = NextScatt.apply_range(Schedule); 1116 NextScatt = NextScatt.apply_range(AccessRelation); 1117 NextScatt = NextScatt.apply_domain(Schedule); 1118 NextScatt = NextScatt.apply_domain(AccessRelation); 1119 1120 isl::set Deltas = NextScatt.deltas(); 1121 return Deltas; 1122 } 1123 1124 bool MemoryAccess::isStrideX(isl::map Schedule, int StrideWidth) const { 1125 isl::set Stride, StrideX; 1126 bool IsStrideX; 1127 1128 Stride = getStride(Schedule); 1129 StrideX = isl::set::universe(Stride.get_space()); 1130 for (unsigned i = 0; i < StrideX.dim(isl::dim::set) - 1; i++) 1131 StrideX = StrideX.fix_si(isl::dim::set, i, 0); 1132 StrideX = StrideX.fix_si(isl::dim::set, StrideX.dim(isl::dim::set) - 1, 1133 StrideWidth); 1134 IsStrideX = Stride.is_subset(StrideX); 1135 1136 return IsStrideX; 1137 } 1138 1139 bool MemoryAccess::isStrideZero(isl::map Schedule) const { 1140 return isStrideX(Schedule, 0); 1141 } 1142 1143 bool MemoryAccess::isStrideOne(isl::map Schedule) const { 1144 return isStrideX(Schedule, 1); 1145 } 1146 1147 void MemoryAccess::setAccessRelation(isl::map NewAccess) { 1148 AccessRelation = NewAccess; 1149 } 1150 1151 void MemoryAccess::setNewAccessRelation(isl::map NewAccess) { 1152 assert(NewAccess); 1153 1154 #ifndef NDEBUG 1155 // Check domain space compatibility. 1156 isl::space NewSpace = NewAccess.get_space(); 1157 isl::space NewDomainSpace = NewSpace.domain(); 1158 isl::space OriginalDomainSpace = getStatement()->getDomainSpace(); 1159 assert(OriginalDomainSpace.has_equal_tuples(NewDomainSpace)); 1160 1161 // Reads must be executed unconditionally. Writes might be executed in a 1162 // subdomain only. 1163 if (isRead()) { 1164 // Check whether there is an access for every statement instance. 1165 isl::set StmtDomain = getStatement()->getDomain(); 1166 StmtDomain = 1167 StmtDomain.intersect_params(getStatement()->getParent()->getContext()); 1168 isl::set NewDomain = NewAccess.domain(); 1169 assert(StmtDomain.is_subset(NewDomain) && 1170 "Partial READ accesses not supported"); 1171 } 1172 1173 isl::space NewAccessSpace = NewAccess.get_space(); 1174 assert(NewAccessSpace.has_tuple_id(isl::dim::set) && 1175 "Must specify the array that is accessed"); 1176 isl::id NewArrayId = NewAccessSpace.get_tuple_id(isl::dim::set); 1177 auto *SAI = static_cast<ScopArrayInfo *>(NewArrayId.get_user()); 1178 assert(SAI && "Must set a ScopArrayInfo"); 1179 1180 if (SAI->isArrayKind() && SAI->getBasePtrOriginSAI()) { 1181 InvariantEquivClassTy *EqClass = 1182 getStatement()->getParent()->lookupInvariantEquivClass( 1183 SAI->getBasePtr()); 1184 assert(EqClass && 1185 "Access functions to indirect arrays must have an invariant and " 1186 "hoisted base pointer"); 1187 } 1188 1189 // Check whether access dimensions correspond to number of dimensions of the 1190 // accesses array. 1191 auto Dims = SAI->getNumberOfDimensions(); 1192 assert(NewAccessSpace.dim(isl::dim::set) == Dims && 1193 "Access dims must match array dims"); 1194 #endif 1195 1196 NewAccess = NewAccess.gist_domain(getStatement()->getDomain()); 1197 NewAccessRelation = NewAccess; 1198 } 1199 1200 bool MemoryAccess::isLatestPartialAccess() const { 1201 isl::set StmtDom = getStatement()->getDomain(); 1202 isl::set AccDom = getLatestAccessRelation().domain(); 1203 1204 return !StmtDom.is_subset(AccDom); 1205 } 1206 1207 //===----------------------------------------------------------------------===// 1208 1209 isl::map ScopStmt::getSchedule() const { 1210 isl::set Domain = getDomain(); 1211 if (Domain.is_empty()) 1212 return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace()))); 1213 auto Schedule = getParent()->getSchedule(); 1214 if (!Schedule) 1215 return nullptr; 1216 Schedule = Schedule.intersect_domain(isl::union_set(Domain)); 1217 if (Schedule.is_empty()) 1218 return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace()))); 1219 isl::map M = M.from_union_map(Schedule); 1220 M = M.coalesce(); 1221 M = M.gist_domain(Domain); 1222 M = M.coalesce(); 1223 return M; 1224 } 1225 1226 void ScopStmt::restrictDomain(isl::set NewDomain) { 1227 assert(NewDomain.is_subset(Domain) && 1228 "New domain is not a subset of old domain!"); 1229 Domain = NewDomain; 1230 } 1231 1232 void ScopStmt::addAccess(MemoryAccess *Access, bool Prepend) { 1233 Instruction *AccessInst = Access->getAccessInstruction(); 1234 1235 if (Access->isArrayKind()) { 1236 MemoryAccessList &MAL = InstructionToAccess[AccessInst]; 1237 MAL.emplace_front(Access); 1238 } else if (Access->isValueKind() && Access->isWrite()) { 1239 Instruction *AccessVal = cast<Instruction>(Access->getAccessValue()); 1240 assert(!ValueWrites.lookup(AccessVal)); 1241 1242 ValueWrites[AccessVal] = Access; 1243 } else if (Access->isValueKind() && Access->isRead()) { 1244 Value *AccessVal = Access->getAccessValue(); 1245 assert(!ValueReads.lookup(AccessVal)); 1246 1247 ValueReads[AccessVal] = Access; 1248 } else if (Access->isAnyPHIKind() && Access->isWrite()) { 1249 PHINode *PHI = cast<PHINode>(Access->getAccessValue()); 1250 assert(!PHIWrites.lookup(PHI)); 1251 1252 PHIWrites[PHI] = Access; 1253 } else if (Access->isAnyPHIKind() && Access->isRead()) { 1254 PHINode *PHI = cast<PHINode>(Access->getAccessValue()); 1255 assert(!PHIReads.lookup(PHI)); 1256 1257 PHIReads[PHI] = Access; 1258 } 1259 1260 if (Prepend) { 1261 MemAccs.insert(MemAccs.begin(), Access); 1262 return; 1263 } 1264 MemAccs.push_back(Access); 1265 } 1266 1267 void ScopStmt::realignParams() { 1268 for (MemoryAccess *MA : *this) 1269 MA->realignParams(); 1270 1271 isl::set Ctx = Parent.getContext(); 1272 InvalidDomain = InvalidDomain.gist_params(Ctx); 1273 Domain = Domain.gist_params(Ctx); 1274 } 1275 1276 /// Add @p BSet to set @p BoundedParts if @p BSet is bounded. 1277 static isl::set collectBoundedParts(isl::set S) { 1278 isl::set BoundedParts = isl::set::empty(S.get_space()); 1279 for (isl::basic_set BSet : S.get_basic_set_list()) 1280 if (BSet.is_bounded()) 1281 BoundedParts = BoundedParts.unite(isl::set(BSet)); 1282 return BoundedParts; 1283 } 1284 1285 /// Compute the (un)bounded parts of @p S wrt. to dimension @p Dim. 1286 /// 1287 /// @returns A separation of @p S into first an unbounded then a bounded subset, 1288 /// both with regards to the dimension @p Dim. 1289 static std::pair<isl::set, isl::set> partitionSetParts(isl::set S, 1290 unsigned Dim) { 1291 for (unsigned u = 0, e = S.n_dim(); u < e; u++) 1292 S = S.lower_bound_si(isl::dim::set, u, 0); 1293 1294 unsigned NumDimsS = S.n_dim(); 1295 isl::set OnlyDimS = S; 1296 1297 // Remove dimensions that are greater than Dim as they are not interesting. 1298 assert(NumDimsS >= Dim + 1); 1299 OnlyDimS = OnlyDimS.project_out(isl::dim::set, Dim + 1, NumDimsS - Dim - 1); 1300 1301 // Create artificial parametric upper bounds for dimensions smaller than Dim 1302 // as we are not interested in them. 1303 OnlyDimS = OnlyDimS.insert_dims(isl::dim::param, 0, Dim); 1304 1305 for (unsigned u = 0; u < Dim; u++) { 1306 isl::constraint C = isl::constraint::alloc_inequality( 1307 isl::local_space(OnlyDimS.get_space())); 1308 C = C.set_coefficient_si(isl::dim::param, u, 1); 1309 C = C.set_coefficient_si(isl::dim::set, u, -1); 1310 OnlyDimS = OnlyDimS.add_constraint(C); 1311 } 1312 1313 // Collect all bounded parts of OnlyDimS. 1314 isl::set BoundedParts = collectBoundedParts(OnlyDimS); 1315 1316 // Create the dimensions greater than Dim again. 1317 BoundedParts = 1318 BoundedParts.insert_dims(isl::dim::set, Dim + 1, NumDimsS - Dim - 1); 1319 1320 // Remove the artificial upper bound parameters again. 1321 BoundedParts = BoundedParts.remove_dims(isl::dim::param, 0, Dim); 1322 1323 isl::set UnboundedParts = S.subtract(BoundedParts); 1324 return std::make_pair(UnboundedParts, BoundedParts); 1325 } 1326 1327 /// Create the conditions under which @p L @p Pred @p R is true. 1328 static isl::set buildConditionSet(ICmpInst::Predicate Pred, isl::pw_aff L, 1329 isl::pw_aff R) { 1330 switch (Pred) { 1331 case ICmpInst::ICMP_EQ: 1332 return L.eq_set(R); 1333 case ICmpInst::ICMP_NE: 1334 return L.ne_set(R); 1335 case ICmpInst::ICMP_SLT: 1336 return L.lt_set(R); 1337 case ICmpInst::ICMP_SLE: 1338 return L.le_set(R); 1339 case ICmpInst::ICMP_SGT: 1340 return L.gt_set(R); 1341 case ICmpInst::ICMP_SGE: 1342 return L.ge_set(R); 1343 case ICmpInst::ICMP_ULT: 1344 return L.lt_set(R); 1345 case ICmpInst::ICMP_UGT: 1346 return L.gt_set(R); 1347 case ICmpInst::ICMP_ULE: 1348 return L.le_set(R); 1349 case ICmpInst::ICMP_UGE: 1350 return L.ge_set(R); 1351 default: 1352 llvm_unreachable("Non integer predicate not supported"); 1353 } 1354 } 1355 1356 /// Compute the isl representation for the SCEV @p E in this BB. 1357 /// 1358 /// @param S The Scop in which @p BB resides in. 1359 /// @param BB The BB for which isl representation is to be 1360 /// computed. 1361 /// @param InvalidDomainMap A map of BB to their invalid domains. 1362 /// @param E The SCEV that should be translated. 1363 /// @param NonNegative Flag to indicate the @p E has to be non-negative. 1364 /// 1365 /// Note that this function will also adjust the invalid context accordingly. 1366 1367 __isl_give isl_pw_aff * 1368 getPwAff(Scop &S, BasicBlock *BB, 1369 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, const SCEV *E, 1370 bool NonNegative = false) { 1371 PWACtx PWAC = S.getPwAff(E, BB, NonNegative); 1372 InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second); 1373 return PWAC.first.release(); 1374 } 1375 1376 /// Build the conditions sets for the switch @p SI in the @p Domain. 1377 /// 1378 /// This will fill @p ConditionSets with the conditions under which control 1379 /// will be moved from @p SI to its successors. Hence, @p ConditionSets will 1380 /// have as many elements as @p SI has successors. 1381 bool buildConditionSets(Scop &S, BasicBlock *BB, SwitchInst *SI, Loop *L, 1382 __isl_keep isl_set *Domain, 1383 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 1384 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) { 1385 Value *Condition = getConditionFromTerminator(SI); 1386 assert(Condition && "No condition for switch"); 1387 1388 ScalarEvolution &SE = *S.getSE(); 1389 isl_pw_aff *LHS, *RHS; 1390 LHS = getPwAff(S, BB, InvalidDomainMap, SE.getSCEVAtScope(Condition, L)); 1391 1392 unsigned NumSuccessors = SI->getNumSuccessors(); 1393 ConditionSets.resize(NumSuccessors); 1394 for (auto &Case : SI->cases()) { 1395 unsigned Idx = Case.getSuccessorIndex(); 1396 ConstantInt *CaseValue = Case.getCaseValue(); 1397 1398 RHS = getPwAff(S, BB, InvalidDomainMap, SE.getSCEV(CaseValue)); 1399 isl_set *CaseConditionSet = 1400 buildConditionSet(ICmpInst::ICMP_EQ, isl::manage_copy(LHS), 1401 isl::manage(RHS)) 1402 .release(); 1403 ConditionSets[Idx] = isl_set_coalesce( 1404 isl_set_intersect(CaseConditionSet, isl_set_copy(Domain))); 1405 } 1406 1407 assert(ConditionSets[0] == nullptr && "Default condition set was set"); 1408 isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]); 1409 for (unsigned u = 2; u < NumSuccessors; u++) 1410 ConditionSetUnion = 1411 isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u])); 1412 ConditionSets[0] = isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion); 1413 1414 isl_pw_aff_free(LHS); 1415 1416 return true; 1417 } 1418 1419 /// Build condition sets for unsigned ICmpInst(s). 1420 /// Special handling is required for unsigned operands to ensure that if 1421 /// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst 1422 /// it should wrap around. 1423 /// 1424 /// @param IsStrictUpperBound holds information on the predicate relation 1425 /// between TestVal and UpperBound, i.e, 1426 /// TestVal < UpperBound OR TestVal <= UpperBound 1427 __isl_give isl_set * 1428 buildUnsignedConditionSets(Scop &S, BasicBlock *BB, Value *Condition, 1429 __isl_keep isl_set *Domain, const SCEV *SCEV_TestVal, 1430 const SCEV *SCEV_UpperBound, 1431 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 1432 bool IsStrictUpperBound) { 1433 // Do not take NonNeg assumption on TestVal 1434 // as it might have MSB (Sign bit) set. 1435 isl_pw_aff *TestVal = getPwAff(S, BB, InvalidDomainMap, SCEV_TestVal, false); 1436 // Take NonNeg assumption on UpperBound. 1437 isl_pw_aff *UpperBound = 1438 getPwAff(S, BB, InvalidDomainMap, SCEV_UpperBound, true); 1439 1440 // 0 <= TestVal 1441 isl_set *First = 1442 isl_pw_aff_le_set(isl_pw_aff_zero_on_domain(isl_local_space_from_space( 1443 isl_pw_aff_get_domain_space(TestVal))), 1444 isl_pw_aff_copy(TestVal)); 1445 1446 isl_set *Second; 1447 if (IsStrictUpperBound) 1448 // TestVal < UpperBound 1449 Second = isl_pw_aff_lt_set(TestVal, UpperBound); 1450 else 1451 // TestVal <= UpperBound 1452 Second = isl_pw_aff_le_set(TestVal, UpperBound); 1453 1454 isl_set *ConsequenceCondSet = isl_set_intersect(First, Second); 1455 return ConsequenceCondSet; 1456 } 1457 1458 /// Build the conditions sets for the branch condition @p Condition in 1459 /// the @p Domain. 1460 /// 1461 /// This will fill @p ConditionSets with the conditions under which control 1462 /// will be moved from @p TI to its successors. Hence, @p ConditionSets will 1463 /// have as many elements as @p TI has successors. If @p TI is nullptr the 1464 /// context under which @p Condition is true/false will be returned as the 1465 /// new elements of @p ConditionSets. 1466 bool buildConditionSets(Scop &S, BasicBlock *BB, Value *Condition, 1467 Instruction *TI, Loop *L, __isl_keep isl_set *Domain, 1468 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 1469 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) { 1470 ScalarEvolution &SE = *S.getSE(); 1471 isl_set *ConsequenceCondSet = nullptr; 1472 1473 if (auto Load = dyn_cast<LoadInst>(Condition)) { 1474 const SCEV *LHSSCEV = SE.getSCEVAtScope(Load, L); 1475 const SCEV *RHSSCEV = SE.getZero(LHSSCEV->getType()); 1476 bool NonNeg = false; 1477 isl_pw_aff *LHS = getPwAff(S, BB, InvalidDomainMap, LHSSCEV, NonNeg); 1478 isl_pw_aff *RHS = getPwAff(S, BB, InvalidDomainMap, RHSSCEV, NonNeg); 1479 ConsequenceCondSet = buildConditionSet(ICmpInst::ICMP_SLE, isl::manage(LHS), 1480 isl::manage(RHS)) 1481 .release(); 1482 } else if (auto *PHI = dyn_cast<PHINode>(Condition)) { 1483 auto *Unique = dyn_cast<ConstantInt>( 1484 getUniqueNonErrorValue(PHI, &S.getRegion(), *S.getLI(), *S.getDT())); 1485 1486 if (Unique->isZero()) 1487 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain)); 1488 else 1489 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain)); 1490 } else if (auto *CCond = dyn_cast<ConstantInt>(Condition)) { 1491 if (CCond->isZero()) 1492 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain)); 1493 else 1494 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain)); 1495 } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) { 1496 auto Opcode = BinOp->getOpcode(); 1497 assert(Opcode == Instruction::And || Opcode == Instruction::Or); 1498 1499 bool Valid = buildConditionSets(S, BB, BinOp->getOperand(0), TI, L, Domain, 1500 InvalidDomainMap, ConditionSets) && 1501 buildConditionSets(S, BB, BinOp->getOperand(1), TI, L, Domain, 1502 InvalidDomainMap, ConditionSets); 1503 if (!Valid) { 1504 while (!ConditionSets.empty()) 1505 isl_set_free(ConditionSets.pop_back_val()); 1506 return false; 1507 } 1508 1509 isl_set_free(ConditionSets.pop_back_val()); 1510 isl_set *ConsCondPart0 = ConditionSets.pop_back_val(); 1511 isl_set_free(ConditionSets.pop_back_val()); 1512 isl_set *ConsCondPart1 = ConditionSets.pop_back_val(); 1513 1514 if (Opcode == Instruction::And) 1515 ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1); 1516 else 1517 ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1); 1518 } else { 1519 auto *ICond = dyn_cast<ICmpInst>(Condition); 1520 assert(ICond && 1521 "Condition of exiting branch was neither constant nor ICmp!"); 1522 1523 LoopInfo &LI = *S.getLI(); 1524 DominatorTree &DT = *S.getDT(); 1525 Region &R = S.getRegion(); 1526 1527 isl_pw_aff *LHS, *RHS; 1528 // For unsigned comparisons we assumed the signed bit of neither operand 1529 // to be set. The comparison is equal to a signed comparison under this 1530 // assumption. 1531 bool NonNeg = ICond->isUnsigned(); 1532 const SCEV *LeftOperand = SE.getSCEVAtScope(ICond->getOperand(0), L), 1533 *RightOperand = SE.getSCEVAtScope(ICond->getOperand(1), L); 1534 1535 LeftOperand = tryForwardThroughPHI(LeftOperand, R, SE, LI, DT); 1536 RightOperand = tryForwardThroughPHI(RightOperand, R, SE, LI, DT); 1537 1538 switch (ICond->getPredicate()) { 1539 case ICmpInst::ICMP_ULT: 1540 ConsequenceCondSet = 1541 buildUnsignedConditionSets(S, BB, Condition, Domain, LeftOperand, 1542 RightOperand, InvalidDomainMap, true); 1543 break; 1544 case ICmpInst::ICMP_ULE: 1545 ConsequenceCondSet = 1546 buildUnsignedConditionSets(S, BB, Condition, Domain, LeftOperand, 1547 RightOperand, InvalidDomainMap, false); 1548 break; 1549 case ICmpInst::ICMP_UGT: 1550 ConsequenceCondSet = 1551 buildUnsignedConditionSets(S, BB, Condition, Domain, RightOperand, 1552 LeftOperand, InvalidDomainMap, true); 1553 break; 1554 case ICmpInst::ICMP_UGE: 1555 ConsequenceCondSet = 1556 buildUnsignedConditionSets(S, BB, Condition, Domain, RightOperand, 1557 LeftOperand, InvalidDomainMap, false); 1558 break; 1559 default: 1560 LHS = getPwAff(S, BB, InvalidDomainMap, LeftOperand, NonNeg); 1561 RHS = getPwAff(S, BB, InvalidDomainMap, RightOperand, NonNeg); 1562 ConsequenceCondSet = buildConditionSet(ICond->getPredicate(), 1563 isl::manage(LHS), isl::manage(RHS)) 1564 .release(); 1565 break; 1566 } 1567 } 1568 1569 // If no terminator was given we are only looking for parameter constraints 1570 // under which @p Condition is true/false. 1571 if (!TI) 1572 ConsequenceCondSet = isl_set_params(ConsequenceCondSet); 1573 assert(ConsequenceCondSet); 1574 ConsequenceCondSet = isl_set_coalesce( 1575 isl_set_intersect(ConsequenceCondSet, isl_set_copy(Domain))); 1576 1577 isl_set *AlternativeCondSet = nullptr; 1578 bool TooComplex = 1579 isl_set_n_basic_set(ConsequenceCondSet) >= MaxDisjunctsInDomain; 1580 1581 if (!TooComplex) { 1582 AlternativeCondSet = isl_set_subtract(isl_set_copy(Domain), 1583 isl_set_copy(ConsequenceCondSet)); 1584 TooComplex = 1585 isl_set_n_basic_set(AlternativeCondSet) >= MaxDisjunctsInDomain; 1586 } 1587 1588 if (TooComplex) { 1589 S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc(), 1590 TI ? TI->getParent() : nullptr /* BasicBlock */); 1591 isl_set_free(AlternativeCondSet); 1592 isl_set_free(ConsequenceCondSet); 1593 return false; 1594 } 1595 1596 ConditionSets.push_back(ConsequenceCondSet); 1597 ConditionSets.push_back(isl_set_coalesce(AlternativeCondSet)); 1598 1599 return true; 1600 } 1601 1602 /// Build the conditions sets for the terminator @p TI in the @p Domain. 1603 /// 1604 /// This will fill @p ConditionSets with the conditions under which control 1605 /// will be moved from @p TI to its successors. Hence, @p ConditionSets will 1606 /// have as many elements as @p TI has successors. 1607 bool buildConditionSets(Scop &S, BasicBlock *BB, Instruction *TI, Loop *L, 1608 __isl_keep isl_set *Domain, 1609 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, 1610 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) { 1611 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) 1612 return buildConditionSets(S, BB, SI, L, Domain, InvalidDomainMap, 1613 ConditionSets); 1614 1615 assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch."); 1616 1617 if (TI->getNumSuccessors() == 1) { 1618 ConditionSets.push_back(isl_set_copy(Domain)); 1619 return true; 1620 } 1621 1622 Value *Condition = getConditionFromTerminator(TI); 1623 assert(Condition && "No condition for Terminator"); 1624 1625 return buildConditionSets(S, BB, Condition, TI, L, Domain, InvalidDomainMap, 1626 ConditionSets); 1627 } 1628 1629 ScopStmt::ScopStmt(Scop &parent, Region &R, StringRef Name, 1630 Loop *SurroundingLoop, 1631 std::vector<Instruction *> EntryBlockInstructions) 1632 : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), R(&R), 1633 Build(nullptr), BaseName(Name), SurroundingLoop(SurroundingLoop), 1634 Instructions(EntryBlockInstructions) {} 1635 1636 ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, StringRef Name, 1637 Loop *SurroundingLoop, 1638 std::vector<Instruction *> Instructions) 1639 : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), BB(&bb), 1640 Build(nullptr), BaseName(Name), SurroundingLoop(SurroundingLoop), 1641 Instructions(Instructions) {} 1642 1643 ScopStmt::ScopStmt(Scop &parent, isl::map SourceRel, isl::map TargetRel, 1644 isl::set NewDomain) 1645 : Parent(parent), InvalidDomain(nullptr), Domain(NewDomain), 1646 Build(nullptr) { 1647 BaseName = getIslCompatibleName("CopyStmt_", "", 1648 std::to_string(parent.getCopyStmtsNum())); 1649 isl::id Id = isl::id::alloc(getIslCtx(), getBaseName(), this); 1650 Domain = Domain.set_tuple_id(Id); 1651 TargetRel = TargetRel.set_tuple_id(isl::dim::in, Id); 1652 auto *Access = 1653 new MemoryAccess(this, MemoryAccess::AccessType::MUST_WRITE, TargetRel); 1654 parent.addAccessFunction(Access); 1655 addAccess(Access); 1656 SourceRel = SourceRel.set_tuple_id(isl::dim::in, Id); 1657 Access = new MemoryAccess(this, MemoryAccess::AccessType::READ, SourceRel); 1658 parent.addAccessFunction(Access); 1659 addAccess(Access); 1660 } 1661 1662 ScopStmt::~ScopStmt() = default; 1663 1664 std::string ScopStmt::getDomainStr() const { return Domain.to_str(); } 1665 1666 std::string ScopStmt::getScheduleStr() const { 1667 auto *S = getSchedule().release(); 1668 if (!S) 1669 return {}; 1670 auto Str = stringFromIslObj(S); 1671 isl_map_free(S); 1672 return Str; 1673 } 1674 1675 void ScopStmt::setInvalidDomain(isl::set ID) { InvalidDomain = ID; } 1676 1677 BasicBlock *ScopStmt::getEntryBlock() const { 1678 if (isBlockStmt()) 1679 return getBasicBlock(); 1680 return getRegion()->getEntry(); 1681 } 1682 1683 unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); } 1684 1685 const char *ScopStmt::getBaseName() const { return BaseName.c_str(); } 1686 1687 Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const { 1688 return NestLoops[Dimension]; 1689 } 1690 1691 isl::ctx ScopStmt::getIslCtx() const { return Parent.getIslCtx(); } 1692 1693 isl::set ScopStmt::getDomain() const { return Domain; } 1694 1695 isl::space ScopStmt::getDomainSpace() const { return Domain.get_space(); } 1696 1697 isl::id ScopStmt::getDomainId() const { return Domain.get_tuple_id(); } 1698 1699 void ScopStmt::printInstructions(raw_ostream &OS) const { 1700 OS << "Instructions {\n"; 1701 1702 for (Instruction *Inst : Instructions) 1703 OS.indent(16) << *Inst << "\n"; 1704 1705 OS.indent(12) << "}\n"; 1706 } 1707 1708 void ScopStmt::print(raw_ostream &OS, bool PrintInstructions) const { 1709 OS << "\t" << getBaseName() << "\n"; 1710 OS.indent(12) << "Domain :=\n"; 1711 1712 if (Domain) { 1713 OS.indent(16) << getDomainStr() << ";\n"; 1714 } else 1715 OS.indent(16) << "n/a\n"; 1716 1717 OS.indent(12) << "Schedule :=\n"; 1718 1719 if (Domain) { 1720 OS.indent(16) << getScheduleStr() << ";\n"; 1721 } else 1722 OS.indent(16) << "n/a\n"; 1723 1724 for (MemoryAccess *Access : MemAccs) 1725 Access->print(OS); 1726 1727 if (PrintInstructions) 1728 printInstructions(OS.indent(12)); 1729 } 1730 1731 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1732 LLVM_DUMP_METHOD void ScopStmt::dump() const { print(dbgs(), true); } 1733 #endif 1734 1735 void ScopStmt::removeAccessData(MemoryAccess *MA) { 1736 if (MA->isRead() && MA->isOriginalValueKind()) { 1737 bool Found = ValueReads.erase(MA->getAccessValue()); 1738 (void)Found; 1739 assert(Found && "Expected access data not found"); 1740 } 1741 if (MA->isWrite() && MA->isOriginalValueKind()) { 1742 bool Found = ValueWrites.erase(cast<Instruction>(MA->getAccessValue())); 1743 (void)Found; 1744 assert(Found && "Expected access data not found"); 1745 } 1746 if (MA->isWrite() && MA->isOriginalAnyPHIKind()) { 1747 bool Found = PHIWrites.erase(cast<PHINode>(MA->getAccessInstruction())); 1748 (void)Found; 1749 assert(Found && "Expected access data not found"); 1750 } 1751 if (MA->isRead() && MA->isOriginalAnyPHIKind()) { 1752 bool Found = PHIReads.erase(cast<PHINode>(MA->getAccessInstruction())); 1753 (void)Found; 1754 assert(Found && "Expected access data not found"); 1755 } 1756 } 1757 1758 void ScopStmt::removeMemoryAccess(MemoryAccess *MA) { 1759 // Remove the memory accesses from this statement together with all scalar 1760 // accesses that were caused by it. MemoryKind::Value READs have no access 1761 // instruction, hence would not be removed by this function. However, it is 1762 // only used for invariant LoadInst accesses, its arguments are always affine, 1763 // hence synthesizable, and therefore there are no MemoryKind::Value READ 1764 // accesses to be removed. 1765 auto Predicate = [&](MemoryAccess *Acc) { 1766 return Acc->getAccessInstruction() == MA->getAccessInstruction(); 1767 }; 1768 for (auto *MA : MemAccs) { 1769 if (Predicate(MA)) { 1770 removeAccessData(MA); 1771 Parent.removeAccessData(MA); 1772 } 1773 } 1774 MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate), 1775 MemAccs.end()); 1776 InstructionToAccess.erase(MA->getAccessInstruction()); 1777 } 1778 1779 void ScopStmt::removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting) { 1780 if (AfterHoisting) { 1781 auto MAIt = std::find(MemAccs.begin(), MemAccs.end(), MA); 1782 assert(MAIt != MemAccs.end()); 1783 MemAccs.erase(MAIt); 1784 1785 removeAccessData(MA); 1786 Parent.removeAccessData(MA); 1787 } 1788 1789 auto It = InstructionToAccess.find(MA->getAccessInstruction()); 1790 if (It != InstructionToAccess.end()) { 1791 It->second.remove(MA); 1792 if (It->second.empty()) 1793 InstructionToAccess.erase(MA->getAccessInstruction()); 1794 } 1795 } 1796 1797 MemoryAccess *ScopStmt::ensureValueRead(Value *V) { 1798 MemoryAccess *Access = lookupInputAccessOf(V); 1799 if (Access) 1800 return Access; 1801 1802 ScopArrayInfo *SAI = 1803 Parent.getOrCreateScopArrayInfo(V, V->getType(), {}, MemoryKind::Value); 1804 Access = new MemoryAccess(this, nullptr, MemoryAccess::READ, V, V->getType(), 1805 true, {}, {}, V, MemoryKind::Value); 1806 Parent.addAccessFunction(Access); 1807 Access->buildAccessRelation(SAI); 1808 addAccess(Access); 1809 Parent.addAccessData(Access); 1810 return Access; 1811 } 1812 1813 raw_ostream &polly::operator<<(raw_ostream &OS, const ScopStmt &S) { 1814 S.print(OS, PollyPrintInstructions); 1815 return OS; 1816 } 1817 1818 //===----------------------------------------------------------------------===// 1819 /// Scop class implement 1820 1821 void Scop::setContext(isl::set NewContext) { 1822 Context = NewContext.align_params(Context.get_space()); 1823 } 1824 1825 namespace { 1826 1827 /// Remap parameter values but keep AddRecs valid wrt. invariant loads. 1828 struct SCEVSensitiveParameterRewriter 1829 : public SCEVRewriteVisitor<SCEVSensitiveParameterRewriter> { 1830 const ValueToValueMap &VMap; 1831 1832 public: 1833 SCEVSensitiveParameterRewriter(const ValueToValueMap &VMap, 1834 ScalarEvolution &SE) 1835 : SCEVRewriteVisitor(SE), VMap(VMap) {} 1836 1837 static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE, 1838 const ValueToValueMap &VMap) { 1839 SCEVSensitiveParameterRewriter SSPR(VMap, SE); 1840 return SSPR.visit(E); 1841 } 1842 1843 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) { 1844 auto *Start = visit(E->getStart()); 1845 auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0), 1846 visit(E->getStepRecurrence(SE)), 1847 E->getLoop(), SCEV::FlagAnyWrap); 1848 return SE.getAddExpr(Start, AddRec); 1849 } 1850 1851 const SCEV *visitUnknown(const SCEVUnknown *E) { 1852 if (auto *NewValue = VMap.lookup(E->getValue())) 1853 return SE.getUnknown(NewValue); 1854 return E; 1855 } 1856 }; 1857 1858 /// Check whether we should remap a SCEV expression. 1859 struct SCEVFindInsideScop : public SCEVTraversal<SCEVFindInsideScop> { 1860 const ValueToValueMap &VMap; 1861 bool FoundInside = false; 1862 const Scop *S; 1863 1864 public: 1865 SCEVFindInsideScop(const ValueToValueMap &VMap, ScalarEvolution &SE, 1866 const Scop *S) 1867 : SCEVTraversal(*this), VMap(VMap), S(S) {} 1868 1869 static bool hasVariant(const SCEV *E, ScalarEvolution &SE, 1870 const ValueToValueMap &VMap, const Scop *S) { 1871 SCEVFindInsideScop SFIS(VMap, SE, S); 1872 SFIS.visitAll(E); 1873 return SFIS.FoundInside; 1874 } 1875 1876 bool follow(const SCEV *E) { 1877 if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(E)) { 1878 FoundInside |= S->getRegion().contains(AddRec->getLoop()); 1879 } else if (auto *Unknown = dyn_cast<SCEVUnknown>(E)) { 1880 if (Instruction *I = dyn_cast<Instruction>(Unknown->getValue())) 1881 FoundInside |= S->getRegion().contains(I) && !VMap.count(I); 1882 } 1883 return !FoundInside; 1884 } 1885 1886 bool isDone() { return FoundInside; } 1887 }; 1888 } // end anonymous namespace 1889 1890 const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *E) const { 1891 // Check whether it makes sense to rewrite the SCEV. (ScalarEvolution 1892 // doesn't like addition between an AddRec and an expression that 1893 // doesn't have a dominance relationship with it.) 1894 if (SCEVFindInsideScop::hasVariant(E, *SE, InvEquivClassVMap, this)) 1895 return E; 1896 1897 // Rewrite SCEV. 1898 return SCEVSensitiveParameterRewriter::rewrite(E, *SE, InvEquivClassVMap); 1899 } 1900 1901 // This table of function names is used to translate parameter names in more 1902 // human-readable names. This makes it easier to interpret Polly analysis 1903 // results. 1904 StringMap<std::string> KnownNames = { 1905 {"_Z13get_global_idj", "global_id"}, 1906 {"_Z12get_local_idj", "local_id"}, 1907 {"_Z15get_global_sizej", "global_size"}, 1908 {"_Z14get_local_sizej", "local_size"}, 1909 {"_Z12get_work_dimv", "work_dim"}, 1910 {"_Z17get_global_offsetj", "global_offset"}, 1911 {"_Z12get_group_idj", "group_id"}, 1912 {"_Z14get_num_groupsj", "num_groups"}, 1913 }; 1914 1915 static std::string getCallParamName(CallInst *Call) { 1916 std::string Result; 1917 raw_string_ostream OS(Result); 1918 std::string Name = Call->getCalledFunction()->getName(); 1919 1920 auto Iterator = KnownNames.find(Name); 1921 if (Iterator != KnownNames.end()) 1922 Name = "__" + Iterator->getValue(); 1923 OS << Name; 1924 for (auto &Operand : Call->arg_operands()) { 1925 ConstantInt *Op = cast<ConstantInt>(&Operand); 1926 OS << "_" << Op->getValue(); 1927 } 1928 OS.flush(); 1929 return Result; 1930 } 1931 1932 void Scop::createParameterId(const SCEV *Parameter) { 1933 assert(Parameters.count(Parameter)); 1934 assert(!ParameterIds.count(Parameter)); 1935 1936 std::string ParameterName = "p_" + std::to_string(getNumParams() - 1); 1937 1938 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) { 1939 Value *Val = ValueParameter->getValue(); 1940 CallInst *Call = dyn_cast<CallInst>(Val); 1941 1942 if (Call && isConstCall(Call)) { 1943 ParameterName = getCallParamName(Call); 1944 } else if (UseInstructionNames) { 1945 // If this parameter references a specific Value and this value has a name 1946 // we use this name as it is likely to be unique and more useful than just 1947 // a number. 1948 if (Val->hasName()) 1949 ParameterName = Val->getName(); 1950 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) { 1951 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets(); 1952 if (LoadOrigin->hasName()) { 1953 ParameterName += "_loaded_from_"; 1954 ParameterName += 1955 LI->getPointerOperand()->stripInBoundsOffsets()->getName(); 1956 } 1957 } 1958 } 1959 1960 ParameterName = getIslCompatibleName("", ParameterName, ""); 1961 } 1962 1963 isl::id Id = isl::id::alloc(getIslCtx(), ParameterName, 1964 const_cast<void *>((const void *)Parameter)); 1965 ParameterIds[Parameter] = Id; 1966 } 1967 1968 void Scop::addParams(const ParameterSetTy &NewParameters) { 1969 for (const SCEV *Parameter : NewParameters) { 1970 // Normalize the SCEV to get the representing element for an invariant load. 1971 Parameter = extractConstantFactor(Parameter, *SE).second; 1972 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1973 1974 if (Parameters.insert(Parameter)) 1975 createParameterId(Parameter); 1976 } 1977 } 1978 1979 isl::id Scop::getIdForParam(const SCEV *Parameter) const { 1980 // Normalize the SCEV to get the representing element for an invariant load. 1981 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1982 return ParameterIds.lookup(Parameter); 1983 } 1984 1985 isl::set Scop::addNonEmptyDomainConstraints(isl::set C) const { 1986 isl::set DomainContext = getDomains().params(); 1987 return C.intersect_params(DomainContext); 1988 } 1989 1990 bool Scop::isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const { 1991 return DT.dominates(BB, getEntry()); 1992 } 1993 1994 void Scop::addUserAssumptions( 1995 AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI, 1996 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 1997 for (auto &Assumption : AC.assumptions()) { 1998 auto *CI = dyn_cast_or_null<CallInst>(Assumption); 1999 if (!CI || CI->getNumArgOperands() != 1) 2000 continue; 2001 2002 bool InScop = contains(CI); 2003 if (!InScop && !isDominatedBy(DT, CI->getParent())) 2004 continue; 2005 2006 auto *L = LI.getLoopFor(CI->getParent()); 2007 auto *Val = CI->getArgOperand(0); 2008 ParameterSetTy DetectedParams; 2009 if (!isAffineConstraint(Val, &R, L, *SE, DetectedParams)) { 2010 ORE.emit( 2011 OptimizationRemarkAnalysis(DEBUG_TYPE, "IgnoreUserAssumption", CI) 2012 << "Non-affine user assumption ignored."); 2013 continue; 2014 } 2015 2016 // Collect all newly introduced parameters. 2017 ParameterSetTy NewParams; 2018 for (auto *Param : DetectedParams) { 2019 Param = extractConstantFactor(Param, *SE).second; 2020 Param = getRepresentingInvariantLoadSCEV(Param); 2021 if (Parameters.count(Param)) 2022 continue; 2023 NewParams.insert(Param); 2024 } 2025 2026 SmallVector<isl_set *, 2> ConditionSets; 2027 auto *TI = InScop ? CI->getParent()->getTerminator() : nullptr; 2028 BasicBlock *BB = InScop ? CI->getParent() : getRegion().getEntry(); 2029 auto *Dom = InScop ? DomainMap[BB].copy() : Context.copy(); 2030 assert(Dom && "Cannot propagate a nullptr."); 2031 bool Valid = buildConditionSets(*this, BB, Val, TI, L, Dom, 2032 InvalidDomainMap, ConditionSets); 2033 isl_set_free(Dom); 2034 2035 if (!Valid) 2036 continue; 2037 2038 isl_set *AssumptionCtx = nullptr; 2039 if (InScop) { 2040 AssumptionCtx = isl_set_complement(isl_set_params(ConditionSets[1])); 2041 isl_set_free(ConditionSets[0]); 2042 } else { 2043 AssumptionCtx = isl_set_complement(ConditionSets[1]); 2044 AssumptionCtx = isl_set_intersect(AssumptionCtx, ConditionSets[0]); 2045 } 2046 2047 // Project out newly introduced parameters as they are not otherwise useful. 2048 if (!NewParams.empty()) { 2049 for (unsigned u = 0; u < isl_set_n_param(AssumptionCtx); u++) { 2050 auto *Id = isl_set_get_dim_id(AssumptionCtx, isl_dim_param, u); 2051 auto *Param = static_cast<const SCEV *>(isl_id_get_user(Id)); 2052 isl_id_free(Id); 2053 2054 if (!NewParams.count(Param)) 2055 continue; 2056 2057 AssumptionCtx = 2058 isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1); 2059 } 2060 } 2061 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "UserAssumption", CI) 2062 << "Use user assumption: " << stringFromIslObj(AssumptionCtx)); 2063 Context = Context.intersect(isl::manage(AssumptionCtx)); 2064 } 2065 } 2066 2067 void Scop::addUserContext() { 2068 if (UserContextStr.empty()) 2069 return; 2070 2071 isl::set UserContext = isl::set(getIslCtx(), UserContextStr.c_str()); 2072 isl::space Space = getParamSpace(); 2073 if (Space.dim(isl::dim::param) != UserContext.dim(isl::dim::param)) { 2074 std::string SpaceStr = Space.to_str(); 2075 errs() << "Error: the context provided in -polly-context has not the same " 2076 << "number of dimensions than the computed context. Due to this " 2077 << "mismatch, the -polly-context option is ignored. Please provide " 2078 << "the context in the parameter space: " << SpaceStr << ".\n"; 2079 return; 2080 } 2081 2082 for (unsigned i = 0; i < Space.dim(isl::dim::param); i++) { 2083 std::string NameContext = Context.get_dim_name(isl::dim::param, i); 2084 std::string NameUserContext = UserContext.get_dim_name(isl::dim::param, i); 2085 2086 if (NameContext != NameUserContext) { 2087 std::string SpaceStr = Space.to_str(); 2088 errs() << "Error: the name of dimension " << i 2089 << " provided in -polly-context " 2090 << "is '" << NameUserContext << "', but the name in the computed " 2091 << "context is '" << NameContext 2092 << "'. Due to this name mismatch, " 2093 << "the -polly-context option is ignored. Please provide " 2094 << "the context in the parameter space: " << SpaceStr << ".\n"; 2095 return; 2096 } 2097 2098 UserContext = UserContext.set_dim_id(isl::dim::param, i, 2099 Space.get_dim_id(isl::dim::param, i)); 2100 } 2101 2102 Context = Context.intersect(UserContext); 2103 } 2104 2105 void Scop::buildInvariantEquivalenceClasses() { 2106 DenseMap<std::pair<const SCEV *, Type *>, LoadInst *> EquivClasses; 2107 2108 const InvariantLoadsSetTy &RIL = getRequiredInvariantLoads(); 2109 for (LoadInst *LInst : RIL) { 2110 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 2111 2112 Type *Ty = LInst->getType(); 2113 LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)]; 2114 if (ClassRep) { 2115 InvEquivClassVMap[LInst] = ClassRep; 2116 continue; 2117 } 2118 2119 ClassRep = LInst; 2120 InvariantEquivClasses.emplace_back( 2121 InvariantEquivClassTy{PointerSCEV, MemoryAccessList(), nullptr, Ty}); 2122 } 2123 } 2124 2125 void Scop::buildContext() { 2126 isl::space Space = isl::space::params_alloc(getIslCtx(), 0); 2127 Context = isl::set::universe(Space); 2128 InvalidContext = isl::set::empty(Space); 2129 AssumedContext = isl::set::universe(Space); 2130 } 2131 2132 void Scop::addParameterBounds() { 2133 unsigned PDim = 0; 2134 for (auto *Parameter : Parameters) { 2135 ConstantRange SRange = SE->getSignedRange(Parameter); 2136 Context = addRangeBoundsToSet(Context, SRange, PDim++, isl::dim::param); 2137 } 2138 } 2139 2140 static std::vector<isl::id> getFortranArrayIds(Scop::array_range Arrays) { 2141 std::vector<isl::id> OutermostSizeIds; 2142 for (auto Array : Arrays) { 2143 // To check if an array is a Fortran array, we check if it has a isl_pw_aff 2144 // for its outermost dimension. Fortran arrays will have this since the 2145 // outermost dimension size can be picked up from their runtime description. 2146 // TODO: actually need to check if it has a FAD, but for now this works. 2147 if (Array->getNumberOfDimensions() > 0) { 2148 isl::pw_aff PwAff = Array->getDimensionSizePw(0); 2149 if (!PwAff) 2150 continue; 2151 2152 isl::id Id = PwAff.get_dim_id(isl::dim::param, 0); 2153 assert(!Id.is_null() && 2154 "Invalid Id for PwAff expression in Fortran array"); 2155 OutermostSizeIds.push_back(Id); 2156 } 2157 } 2158 return OutermostSizeIds; 2159 } 2160 2161 // The FORTRAN array size parameters are known to be non-negative. 2162 static isl::set boundFortranArrayParams(isl::set Context, 2163 Scop::array_range Arrays) { 2164 std::vector<isl::id> OutermostSizeIds; 2165 OutermostSizeIds = getFortranArrayIds(Arrays); 2166 2167 for (isl::id Id : OutermostSizeIds) { 2168 int dim = Context.find_dim_by_id(isl::dim::param, Id); 2169 Context = Context.lower_bound_si(isl::dim::param, dim, 0); 2170 } 2171 2172 return Context; 2173 } 2174 2175 void Scop::realignParams() { 2176 if (PollyIgnoreParamBounds) 2177 return; 2178 2179 // Add all parameters into a common model. 2180 isl::space Space = getFullParamSpace(); 2181 2182 // Align the parameters of all data structures to the model. 2183 Context = Context.align_params(Space); 2184 2185 // Bound the size of the fortran array dimensions. 2186 Context = boundFortranArrayParams(Context, arrays()); 2187 2188 // As all parameters are known add bounds to them. 2189 addParameterBounds(); 2190 2191 for (ScopStmt &Stmt : *this) 2192 Stmt.realignParams(); 2193 // Simplify the schedule according to the context too. 2194 Schedule = Schedule.gist_domain_params(getContext()); 2195 } 2196 2197 static isl::set simplifyAssumptionContext(isl::set AssumptionContext, 2198 const Scop &S) { 2199 // If we have modeled all blocks in the SCoP that have side effects we can 2200 // simplify the context with the constraints that are needed for anything to 2201 // be executed at all. However, if we have error blocks in the SCoP we already 2202 // assumed some parameter combinations cannot occur and removed them from the 2203 // domains, thus we cannot use the remaining domain to simplify the 2204 // assumptions. 2205 if (!S.hasErrorBlock()) { 2206 auto DomainParameters = S.getDomains().params(); 2207 AssumptionContext = AssumptionContext.gist_params(DomainParameters); 2208 } 2209 2210 AssumptionContext = AssumptionContext.gist_params(S.getContext()); 2211 return AssumptionContext; 2212 } 2213 2214 void Scop::simplifyContexts() { 2215 // The parameter constraints of the iteration domains give us a set of 2216 // constraints that need to hold for all cases where at least a single 2217 // statement iteration is executed in the whole scop. We now simplify the 2218 // assumed context under the assumption that such constraints hold and at 2219 // least a single statement iteration is executed. For cases where no 2220 // statement instances are executed, the assumptions we have taken about 2221 // the executed code do not matter and can be changed. 2222 // 2223 // WARNING: This only holds if the assumptions we have taken do not reduce 2224 // the set of statement instances that are executed. Otherwise we 2225 // may run into a case where the iteration domains suggest that 2226 // for a certain set of parameter constraints no code is executed, 2227 // but in the original program some computation would have been 2228 // performed. In such a case, modifying the run-time conditions and 2229 // possibly influencing the run-time check may cause certain scops 2230 // to not be executed. 2231 // 2232 // Example: 2233 // 2234 // When delinearizing the following code: 2235 // 2236 // for (long i = 0; i < 100; i++) 2237 // for (long j = 0; j < m; j++) 2238 // A[i+p][j] = 1.0; 2239 // 2240 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as 2241 // otherwise we would access out of bound data. Now, knowing that code is 2242 // only executed for the case m >= 0, it is sufficient to assume p >= 0. 2243 AssumedContext = simplifyAssumptionContext(AssumedContext, *this); 2244 InvalidContext = InvalidContext.align_params(getParamSpace()); 2245 } 2246 2247 /// Add the minimal/maximal access in @p Set to @p User. 2248 /// 2249 /// @return True if more accesses should be added, false if we reached the 2250 /// maximal number of run-time checks to be generated. 2251 static bool buildMinMaxAccess(isl::set Set, 2252 Scop::MinMaxVectorTy &MinMaxAccesses, Scop &S) { 2253 isl::pw_multi_aff MinPMA, MaxPMA; 2254 isl::pw_aff LastDimAff; 2255 isl::aff OneAff; 2256 unsigned Pos; 2257 2258 Set = Set.remove_divs(); 2259 polly::simplify(Set); 2260 2261 if (Set.n_basic_set() > RunTimeChecksMaxAccessDisjuncts) 2262 Set = Set.simple_hull(); 2263 2264 // Restrict the number of parameters involved in the access as the lexmin/ 2265 // lexmax computation will take too long if this number is high. 2266 // 2267 // Experiments with a simple test case using an i7 4800MQ: 2268 // 2269 // #Parameters involved | Time (in sec) 2270 // 6 | 0.01 2271 // 7 | 0.04 2272 // 8 | 0.12 2273 // 9 | 0.40 2274 // 10 | 1.54 2275 // 11 | 6.78 2276 // 12 | 30.38 2277 // 2278 if (isl_set_n_param(Set.get()) > RunTimeChecksMaxParameters) { 2279 unsigned InvolvedParams = 0; 2280 for (unsigned u = 0, e = isl_set_n_param(Set.get()); u < e; u++) 2281 if (Set.involves_dims(isl::dim::param, u, 1)) 2282 InvolvedParams++; 2283 2284 if (InvolvedParams > RunTimeChecksMaxParameters) 2285 return false; 2286 } 2287 2288 MinPMA = Set.lexmin_pw_multi_aff(); 2289 MaxPMA = Set.lexmax_pw_multi_aff(); 2290 2291 MinPMA = MinPMA.coalesce(); 2292 MaxPMA = MaxPMA.coalesce(); 2293 2294 // Adjust the last dimension of the maximal access by one as we want to 2295 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer 2296 // we test during code generation might now point after the end of the 2297 // allocated array but we will never dereference it anyway. 2298 assert((!MaxPMA || MaxPMA.dim(isl::dim::out)) && 2299 "Assumed at least one output dimension"); 2300 2301 Pos = MaxPMA.dim(isl::dim::out) - 1; 2302 LastDimAff = MaxPMA.get_pw_aff(Pos); 2303 OneAff = isl::aff(isl::local_space(LastDimAff.get_domain_space())); 2304 OneAff = OneAff.add_constant_si(1); 2305 LastDimAff = LastDimAff.add(OneAff); 2306 MaxPMA = MaxPMA.set_pw_aff(Pos, LastDimAff); 2307 2308 if (!MinPMA || !MaxPMA) 2309 return false; 2310 2311 MinMaxAccesses.push_back(std::make_pair(MinPMA, MaxPMA)); 2312 2313 return true; 2314 } 2315 2316 static isl::set getAccessDomain(MemoryAccess *MA) { 2317 isl::set Domain = MA->getStatement()->getDomain(); 2318 Domain = Domain.project_out(isl::dim::set, 0, Domain.n_dim()); 2319 return Domain.reset_tuple_id(); 2320 } 2321 2322 /// Wrapper function to calculate minimal/maximal accesses to each array. 2323 static bool calculateMinMaxAccess(Scop::AliasGroupTy AliasGroup, Scop &S, 2324 Scop::MinMaxVectorTy &MinMaxAccesses) { 2325 MinMaxAccesses.reserve(AliasGroup.size()); 2326 2327 isl::union_set Domains = S.getDomains(); 2328 isl::union_map Accesses = isl::union_map::empty(S.getParamSpace()); 2329 2330 for (MemoryAccess *MA : AliasGroup) 2331 Accesses = Accesses.add_map(MA->getAccessRelation()); 2332 2333 Accesses = Accesses.intersect_domain(Domains); 2334 isl::union_set Locations = Accesses.range(); 2335 2336 bool LimitReached = false; 2337 for (isl::set Set : Locations.get_set_list()) { 2338 LimitReached |= !buildMinMaxAccess(Set, MinMaxAccesses, S); 2339 if (LimitReached) 2340 break; 2341 } 2342 2343 return !LimitReached; 2344 } 2345 2346 /// Helper to treat non-affine regions and basic blocks the same. 2347 /// 2348 ///{ 2349 2350 /// Return the block that is the representing block for @p RN. 2351 static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) { 2352 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry() 2353 : RN->getNodeAs<BasicBlock>(); 2354 } 2355 2356 /// Return the @p idx'th block that is executed after @p RN. 2357 static inline BasicBlock * 2358 getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx) { 2359 if (RN->isSubRegion()) { 2360 assert(idx == 0); 2361 return RN->getNodeAs<Region>()->getExit(); 2362 } 2363 return TI->getSuccessor(idx); 2364 } 2365 2366 /// Return the smallest loop surrounding @p RN. 2367 static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) { 2368 if (!RN->isSubRegion()) { 2369 BasicBlock *BB = RN->getNodeAs<BasicBlock>(); 2370 Loop *L = LI.getLoopFor(BB); 2371 2372 // Unreachable statements are not considered to belong to a LLVM loop, as 2373 // they are not part of an actual loop in the control flow graph. 2374 // Nevertheless, we handle certain unreachable statements that are common 2375 // when modeling run-time bounds checks as being part of the loop to be 2376 // able to model them and to later eliminate the run-time bounds checks. 2377 // 2378 // Specifically, for basic blocks that terminate in an unreachable and 2379 // where the immediate predecessor is part of a loop, we assume these 2380 // basic blocks belong to the loop the predecessor belongs to. This 2381 // allows us to model the following code. 2382 // 2383 // for (i = 0; i < N; i++) { 2384 // if (i > 1024) 2385 // abort(); <- this abort might be translated to an 2386 // unreachable 2387 // 2388 // A[i] = ... 2389 // } 2390 if (!L && isa<UnreachableInst>(BB->getTerminator()) && BB->getPrevNode()) 2391 L = LI.getLoopFor(BB->getPrevNode()); 2392 return L; 2393 } 2394 2395 Region *NonAffineSubRegion = RN->getNodeAs<Region>(); 2396 Loop *L = LI.getLoopFor(NonAffineSubRegion->getEntry()); 2397 while (L && NonAffineSubRegion->contains(L)) 2398 L = L->getParentLoop(); 2399 return L; 2400 } 2401 2402 /// Get the number of blocks in @p L. 2403 /// 2404 /// The number of blocks in a loop are the number of basic blocks actually 2405 /// belonging to the loop, as well as all single basic blocks that the loop 2406 /// exits to and which terminate in an unreachable instruction. We do not 2407 /// allow such basic blocks in the exit of a scop, hence they belong to the 2408 /// scop and represent run-time conditions which we want to model and 2409 /// subsequently speculate away. 2410 /// 2411 /// @see getRegionNodeLoop for additional details. 2412 unsigned getNumBlocksInLoop(Loop *L) { 2413 unsigned NumBlocks = L->getNumBlocks(); 2414 SmallVector<BasicBlock *, 4> ExitBlocks; 2415 L->getExitBlocks(ExitBlocks); 2416 2417 for (auto ExitBlock : ExitBlocks) { 2418 if (isa<UnreachableInst>(ExitBlock->getTerminator())) 2419 NumBlocks++; 2420 } 2421 return NumBlocks; 2422 } 2423 2424 static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) { 2425 if (!RN->isSubRegion()) 2426 return 1; 2427 2428 Region *R = RN->getNodeAs<Region>(); 2429 return std::distance(R->block_begin(), R->block_end()); 2430 } 2431 2432 static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI, 2433 const DominatorTree &DT) { 2434 if (!RN->isSubRegion()) 2435 return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT); 2436 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks()) 2437 if (isErrorBlock(*BB, R, LI, DT)) 2438 return true; 2439 return false; 2440 } 2441 2442 ///} 2443 2444 isl::set Scop::getDomainConditions(const ScopStmt *Stmt) const { 2445 return getDomainConditions(Stmt->getEntryBlock()); 2446 } 2447 2448 isl::set Scop::getDomainConditions(BasicBlock *BB) const { 2449 auto DIt = DomainMap.find(BB); 2450 if (DIt != DomainMap.end()) 2451 return DIt->getSecond(); 2452 2453 auto &RI = *R.getRegionInfo(); 2454 auto *BBR = RI.getRegionFor(BB); 2455 while (BBR->getEntry() == BB) 2456 BBR = BBR->getParent(); 2457 return getDomainConditions(BBR->getEntry()); 2458 } 2459 2460 bool Scop::buildDomains(Region *R, DominatorTree &DT, LoopInfo &LI, 2461 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 2462 bool IsOnlyNonAffineRegion = isNonAffineSubRegion(R); 2463 auto *EntryBB = R->getEntry(); 2464 auto *L = IsOnlyNonAffineRegion ? nullptr : LI.getLoopFor(EntryBB); 2465 int LD = getRelativeLoopDepth(L); 2466 auto *S = isl_set_universe(isl_space_set_alloc(getIslCtx().get(), 0, LD + 1)); 2467 2468 while (LD-- >= 0) { 2469 L = L->getParentLoop(); 2470 } 2471 2472 InvalidDomainMap[EntryBB] = isl::manage(isl_set_empty(isl_set_get_space(S))); 2473 DomainMap[EntryBB] = isl::manage(S); 2474 2475 if (IsOnlyNonAffineRegion) 2476 return !containsErrorBlock(R->getNode(), *R, LI, DT); 2477 2478 if (!buildDomainsWithBranchConstraints(R, DT, LI, InvalidDomainMap)) 2479 return false; 2480 2481 if (!propagateDomainConstraints(R, DT, LI, InvalidDomainMap)) 2482 return false; 2483 2484 // Error blocks and blocks dominated by them have been assumed to never be 2485 // executed. Representing them in the Scop does not add any value. In fact, 2486 // it is likely to cause issues during construction of the ScopStmts. The 2487 // contents of error blocks have not been verified to be expressible and 2488 // will cause problems when building up a ScopStmt for them. 2489 // Furthermore, basic blocks dominated by error blocks may reference 2490 // instructions in the error block which, if the error block is not modeled, 2491 // can themselves not be constructed properly. To this end we will replace 2492 // the domains of error blocks and those only reachable via error blocks 2493 // with an empty set. Additionally, we will record for each block under which 2494 // parameter combination it would be reached via an error block in its 2495 // InvalidDomain. This information is needed during load hoisting. 2496 if (!propagateInvalidStmtDomains(R, DT, LI, InvalidDomainMap)) 2497 return false; 2498 2499 return true; 2500 } 2501 2502 /// Adjust the dimensions of @p Dom that was constructed for @p OldL 2503 /// to be compatible to domains constructed for loop @p NewL. 2504 /// 2505 /// This function assumes @p NewL and @p OldL are equal or there is a CFG 2506 /// edge from @p OldL to @p NewL. 2507 static isl::set adjustDomainDimensions(Scop &S, isl::set Dom, Loop *OldL, 2508 Loop *NewL) { 2509 // If the loops are the same there is nothing to do. 2510 if (NewL == OldL) 2511 return Dom; 2512 2513 int OldDepth = S.getRelativeLoopDepth(OldL); 2514 int NewDepth = S.getRelativeLoopDepth(NewL); 2515 // If both loops are non-affine loops there is nothing to do. 2516 if (OldDepth == -1 && NewDepth == -1) 2517 return Dom; 2518 2519 // Distinguish three cases: 2520 // 1) The depth is the same but the loops are not. 2521 // => One loop was left one was entered. 2522 // 2) The depth increased from OldL to NewL. 2523 // => One loop was entered, none was left. 2524 // 3) The depth decreased from OldL to NewL. 2525 // => Loops were left were difference of the depths defines how many. 2526 if (OldDepth == NewDepth) { 2527 assert(OldL->getParentLoop() == NewL->getParentLoop()); 2528 Dom = Dom.project_out(isl::dim::set, NewDepth, 1); 2529 Dom = Dom.add_dims(isl::dim::set, 1); 2530 } else if (OldDepth < NewDepth) { 2531 assert(OldDepth + 1 == NewDepth); 2532 auto &R = S.getRegion(); 2533 (void)R; 2534 assert(NewL->getParentLoop() == OldL || 2535 ((!OldL || !R.contains(OldL)) && R.contains(NewL))); 2536 Dom = Dom.add_dims(isl::dim::set, 1); 2537 } else { 2538 assert(OldDepth > NewDepth); 2539 int Diff = OldDepth - NewDepth; 2540 int NumDim = Dom.n_dim(); 2541 assert(NumDim >= Diff); 2542 Dom = Dom.project_out(isl::dim::set, NumDim - Diff, Diff); 2543 } 2544 2545 return Dom; 2546 } 2547 2548 bool Scop::propagateInvalidStmtDomains( 2549 Region *R, DominatorTree &DT, LoopInfo &LI, 2550 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 2551 ReversePostOrderTraversal<Region *> RTraversal(R); 2552 for (auto *RN : RTraversal) { 2553 2554 // Recurse for affine subregions but go on for basic blocks and non-affine 2555 // subregions. 2556 if (RN->isSubRegion()) { 2557 Region *SubRegion = RN->getNodeAs<Region>(); 2558 if (!isNonAffineSubRegion(SubRegion)) { 2559 propagateInvalidStmtDomains(SubRegion, DT, LI, InvalidDomainMap); 2560 continue; 2561 } 2562 } 2563 2564 bool ContainsErrorBlock = containsErrorBlock(RN, getRegion(), LI, DT); 2565 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2566 isl::set &Domain = DomainMap[BB]; 2567 assert(Domain && "Cannot propagate a nullptr"); 2568 2569 isl::set InvalidDomain = InvalidDomainMap[BB]; 2570 2571 bool IsInvalidBlock = ContainsErrorBlock || Domain.is_subset(InvalidDomain); 2572 2573 if (!IsInvalidBlock) { 2574 InvalidDomain = InvalidDomain.intersect(Domain); 2575 } else { 2576 InvalidDomain = Domain; 2577 isl::set DomPar = Domain.params(); 2578 recordAssumption(ERRORBLOCK, DomPar, BB->getTerminator()->getDebugLoc(), 2579 AS_RESTRICTION); 2580 Domain = isl::set::empty(Domain.get_space()); 2581 } 2582 2583 if (InvalidDomain.is_empty()) { 2584 InvalidDomainMap[BB] = InvalidDomain; 2585 continue; 2586 } 2587 2588 auto *BBLoop = getRegionNodeLoop(RN, LI); 2589 auto *TI = BB->getTerminator(); 2590 unsigned NumSuccs = RN->isSubRegion() ? 1 : TI->getNumSuccessors(); 2591 for (unsigned u = 0; u < NumSuccs; u++) { 2592 auto *SuccBB = getRegionNodeSuccessor(RN, TI, u); 2593 2594 // Skip successors outside the SCoP. 2595 if (!contains(SuccBB)) 2596 continue; 2597 2598 // Skip backedges. 2599 if (DT.dominates(SuccBB, BB)) 2600 continue; 2601 2602 Loop *SuccBBLoop = getFirstNonBoxedLoopFor(SuccBB, LI, getBoxedLoops()); 2603 2604 auto AdjustedInvalidDomain = 2605 adjustDomainDimensions(*this, InvalidDomain, BBLoop, SuccBBLoop); 2606 2607 isl::set SuccInvalidDomain = InvalidDomainMap[SuccBB]; 2608 SuccInvalidDomain = SuccInvalidDomain.unite(AdjustedInvalidDomain); 2609 SuccInvalidDomain = SuccInvalidDomain.coalesce(); 2610 unsigned NumConjucts = SuccInvalidDomain.n_basic_set(); 2611 2612 InvalidDomainMap[SuccBB] = SuccInvalidDomain; 2613 2614 // Check if the maximal number of domain disjunctions was reached. 2615 // In case this happens we will bail. 2616 if (NumConjucts < MaxDisjunctsInDomain) 2617 continue; 2618 2619 InvalidDomainMap.erase(BB); 2620 invalidate(COMPLEXITY, TI->getDebugLoc(), TI->getParent()); 2621 return false; 2622 } 2623 2624 InvalidDomainMap[BB] = InvalidDomain; 2625 } 2626 2627 return true; 2628 } 2629 2630 void Scop::propagateDomainConstraintsToRegionExit( 2631 BasicBlock *BB, Loop *BBLoop, 2632 SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, LoopInfo &LI, 2633 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 2634 // Check if the block @p BB is the entry of a region. If so we propagate it's 2635 // domain to the exit block of the region. Otherwise we are done. 2636 auto *RI = R.getRegionInfo(); 2637 auto *BBReg = RI ? RI->getRegionFor(BB) : nullptr; 2638 auto *ExitBB = BBReg ? BBReg->getExit() : nullptr; 2639 if (!BBReg || BBReg->getEntry() != BB || !contains(ExitBB)) 2640 return; 2641 2642 // Do not propagate the domain if there is a loop backedge inside the region 2643 // that would prevent the exit block from being executed. 2644 auto *L = BBLoop; 2645 while (L && contains(L)) { 2646 SmallVector<BasicBlock *, 4> LatchBBs; 2647 BBLoop->getLoopLatches(LatchBBs); 2648 for (auto *LatchBB : LatchBBs) 2649 if (BB != LatchBB && BBReg->contains(LatchBB)) 2650 return; 2651 L = L->getParentLoop(); 2652 } 2653 2654 isl::set Domain = DomainMap[BB]; 2655 assert(Domain && "Cannot propagate a nullptr"); 2656 2657 Loop *ExitBBLoop = getFirstNonBoxedLoopFor(ExitBB, LI, getBoxedLoops()); 2658 2659 // Since the dimensions of @p BB and @p ExitBB might be different we have to 2660 // adjust the domain before we can propagate it. 2661 isl::set AdjustedDomain = 2662 adjustDomainDimensions(*this, Domain, BBLoop, ExitBBLoop); 2663 isl::set &ExitDomain = DomainMap[ExitBB]; 2664 2665 // If the exit domain is not yet created we set it otherwise we "add" the 2666 // current domain. 2667 ExitDomain = ExitDomain ? AdjustedDomain.unite(ExitDomain) : AdjustedDomain; 2668 2669 // Initialize the invalid domain. 2670 InvalidDomainMap[ExitBB] = ExitDomain.empty(ExitDomain.get_space()); 2671 2672 FinishedExitBlocks.insert(ExitBB); 2673 } 2674 2675 bool Scop::buildDomainsWithBranchConstraints( 2676 Region *R, DominatorTree &DT, LoopInfo &LI, 2677 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 2678 // To create the domain for each block in R we iterate over all blocks and 2679 // subregions in R and propagate the conditions under which the current region 2680 // element is executed. To this end we iterate in reverse post order over R as 2681 // it ensures that we first visit all predecessors of a region node (either a 2682 // basic block or a subregion) before we visit the region node itself. 2683 // Initially, only the domain for the SCoP region entry block is set and from 2684 // there we propagate the current domain to all successors, however we add the 2685 // condition that the successor is actually executed next. 2686 // As we are only interested in non-loop carried constraints here we can 2687 // simply skip loop back edges. 2688 2689 SmallPtrSet<BasicBlock *, 8> FinishedExitBlocks; 2690 ReversePostOrderTraversal<Region *> RTraversal(R); 2691 for (auto *RN : RTraversal) { 2692 // Recurse for affine subregions but go on for basic blocks and non-affine 2693 // subregions. 2694 if (RN->isSubRegion()) { 2695 Region *SubRegion = RN->getNodeAs<Region>(); 2696 if (!isNonAffineSubRegion(SubRegion)) { 2697 if (!buildDomainsWithBranchConstraints(SubRegion, DT, LI, 2698 InvalidDomainMap)) 2699 return false; 2700 continue; 2701 } 2702 } 2703 2704 if (containsErrorBlock(RN, getRegion(), LI, DT)) 2705 HasErrorBlock = true; 2706 2707 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2708 Instruction *TI = BB->getTerminator(); 2709 2710 if (isa<UnreachableInst>(TI)) 2711 continue; 2712 2713 isl::set Domain = DomainMap.lookup(BB); 2714 if (!Domain) 2715 continue; 2716 MaxLoopDepth = std::max(MaxLoopDepth, isl_set_n_dim(Domain.get())); 2717 2718 auto *BBLoop = getRegionNodeLoop(RN, LI); 2719 // Propagate the domain from BB directly to blocks that have a superset 2720 // domain, at the moment only region exit nodes of regions that start in BB. 2721 propagateDomainConstraintsToRegionExit(BB, BBLoop, FinishedExitBlocks, LI, 2722 InvalidDomainMap); 2723 2724 // If all successors of BB have been set a domain through the propagation 2725 // above we do not need to build condition sets but can just skip this 2726 // block. However, it is important to note that this is a local property 2727 // with regards to the region @p R. To this end FinishedExitBlocks is a 2728 // local variable. 2729 auto IsFinishedRegionExit = [&FinishedExitBlocks](BasicBlock *SuccBB) { 2730 return FinishedExitBlocks.count(SuccBB); 2731 }; 2732 if (std::all_of(succ_begin(BB), succ_end(BB), IsFinishedRegionExit)) 2733 continue; 2734 2735 // Build the condition sets for the successor nodes of the current region 2736 // node. If it is a non-affine subregion we will always execute the single 2737 // exit node, hence the single entry node domain is the condition set. For 2738 // basic blocks we use the helper function buildConditionSets. 2739 SmallVector<isl_set *, 8> ConditionSets; 2740 if (RN->isSubRegion()) 2741 ConditionSets.push_back(Domain.copy()); 2742 else if (!buildConditionSets(*this, BB, TI, BBLoop, Domain.get(), 2743 InvalidDomainMap, ConditionSets)) 2744 return false; 2745 2746 // Now iterate over the successors and set their initial domain based on 2747 // their condition set. We skip back edges here and have to be careful when 2748 // we leave a loop not to keep constraints over a dimension that doesn't 2749 // exist anymore. 2750 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size()); 2751 for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) { 2752 isl::set CondSet = isl::manage(ConditionSets[u]); 2753 BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u); 2754 2755 // Skip blocks outside the region. 2756 if (!contains(SuccBB)) 2757 continue; 2758 2759 // If we propagate the domain of some block to "SuccBB" we do not have to 2760 // adjust the domain. 2761 if (FinishedExitBlocks.count(SuccBB)) 2762 continue; 2763 2764 // Skip back edges. 2765 if (DT.dominates(SuccBB, BB)) 2766 continue; 2767 2768 Loop *SuccBBLoop = getFirstNonBoxedLoopFor(SuccBB, LI, getBoxedLoops()); 2769 2770 CondSet = adjustDomainDimensions(*this, CondSet, BBLoop, SuccBBLoop); 2771 2772 // Set the domain for the successor or merge it with an existing domain in 2773 // case there are multiple paths (without loop back edges) to the 2774 // successor block. 2775 isl::set &SuccDomain = DomainMap[SuccBB]; 2776 2777 if (SuccDomain) { 2778 SuccDomain = SuccDomain.unite(CondSet).coalesce(); 2779 } else { 2780 // Initialize the invalid domain. 2781 InvalidDomainMap[SuccBB] = CondSet.empty(CondSet.get_space()); 2782 SuccDomain = CondSet; 2783 } 2784 2785 SuccDomain = SuccDomain.detect_equalities(); 2786 2787 // Check if the maximal number of domain disjunctions was reached. 2788 // In case this happens we will clean up and bail. 2789 if (SuccDomain.n_basic_set() < MaxDisjunctsInDomain) 2790 continue; 2791 2792 invalidate(COMPLEXITY, DebugLoc()); 2793 while (++u < ConditionSets.size()) 2794 isl_set_free(ConditionSets[u]); 2795 return false; 2796 } 2797 } 2798 2799 return true; 2800 } 2801 2802 isl::set Scop::getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain, 2803 DominatorTree &DT, 2804 LoopInfo &LI) { 2805 // If @p BB is the ScopEntry we are done 2806 if (R.getEntry() == BB) 2807 return isl::set::universe(Domain.get_space()); 2808 2809 // The region info of this function. 2810 auto &RI = *R.getRegionInfo(); 2811 2812 Loop *BBLoop = getFirstNonBoxedLoopFor(BB, LI, getBoxedLoops()); 2813 2814 // A domain to collect all predecessor domains, thus all conditions under 2815 // which the block is executed. To this end we start with the empty domain. 2816 isl::set PredDom = isl::set::empty(Domain.get_space()); 2817 2818 // Set of regions of which the entry block domain has been propagated to BB. 2819 // all predecessors inside any of the regions can be skipped. 2820 SmallSet<Region *, 8> PropagatedRegions; 2821 2822 for (auto *PredBB : predecessors(BB)) { 2823 // Skip backedges. 2824 if (DT.dominates(BB, PredBB)) 2825 continue; 2826 2827 // If the predecessor is in a region we used for propagation we can skip it. 2828 auto PredBBInRegion = [PredBB](Region *PR) { return PR->contains(PredBB); }; 2829 if (std::any_of(PropagatedRegions.begin(), PropagatedRegions.end(), 2830 PredBBInRegion)) { 2831 continue; 2832 } 2833 2834 // Check if there is a valid region we can use for propagation, thus look 2835 // for a region that contains the predecessor and has @p BB as exit block. 2836 auto *PredR = RI.getRegionFor(PredBB); 2837 while (PredR->getExit() != BB && !PredR->contains(BB)) 2838 PredR->getParent(); 2839 2840 // If a valid region for propagation was found use the entry of that region 2841 // for propagation, otherwise the PredBB directly. 2842 if (PredR->getExit() == BB) { 2843 PredBB = PredR->getEntry(); 2844 PropagatedRegions.insert(PredR); 2845 } 2846 2847 isl::set PredBBDom = getDomainConditions(PredBB); 2848 Loop *PredBBLoop = getFirstNonBoxedLoopFor(PredBB, LI, getBoxedLoops()); 2849 PredBBDom = adjustDomainDimensions(*this, PredBBDom, PredBBLoop, BBLoop); 2850 PredDom = PredDom.unite(PredBBDom); 2851 } 2852 2853 return PredDom; 2854 } 2855 2856 bool Scop::propagateDomainConstraints( 2857 Region *R, DominatorTree &DT, LoopInfo &LI, 2858 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 2859 // Iterate over the region R and propagate the domain constrains from the 2860 // predecessors to the current node. In contrast to the 2861 // buildDomainsWithBranchConstraints function, this one will pull the domain 2862 // information from the predecessors instead of pushing it to the successors. 2863 // Additionally, we assume the domains to be already present in the domain 2864 // map here. However, we iterate again in reverse post order so we know all 2865 // predecessors have been visited before a block or non-affine subregion is 2866 // visited. 2867 2868 ReversePostOrderTraversal<Region *> RTraversal(R); 2869 for (auto *RN : RTraversal) { 2870 // Recurse for affine subregions but go on for basic blocks and non-affine 2871 // subregions. 2872 if (RN->isSubRegion()) { 2873 Region *SubRegion = RN->getNodeAs<Region>(); 2874 if (!isNonAffineSubRegion(SubRegion)) { 2875 if (!propagateDomainConstraints(SubRegion, DT, LI, InvalidDomainMap)) 2876 return false; 2877 continue; 2878 } 2879 } 2880 2881 BasicBlock *BB = getRegionNodeBasicBlock(RN); 2882 isl::set &Domain = DomainMap[BB]; 2883 assert(Domain); 2884 2885 // Under the union of all predecessor conditions we can reach this block. 2886 isl::set PredDom = getPredecessorDomainConstraints(BB, Domain, DT, LI); 2887 Domain = Domain.intersect(PredDom).coalesce(); 2888 Domain = Domain.align_params(getParamSpace()); 2889 2890 Loop *BBLoop = getRegionNodeLoop(RN, LI); 2891 if (BBLoop && BBLoop->getHeader() == BB && contains(BBLoop)) 2892 if (!addLoopBoundsToHeaderDomain(BBLoop, LI, InvalidDomainMap)) 2893 return false; 2894 } 2895 2896 return true; 2897 } 2898 2899 /// Create a map to map from a given iteration to a subsequent iteration. 2900 /// 2901 /// This map maps from SetSpace -> SetSpace where the dimensions @p Dim 2902 /// is incremented by one and all other dimensions are equal, e.g., 2903 /// [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3] 2904 /// 2905 /// if @p Dim is 2 and @p SetSpace has 4 dimensions. 2906 static isl::map createNextIterationMap(isl::space SetSpace, unsigned Dim) { 2907 isl::space MapSpace = SetSpace.map_from_set(); 2908 isl::map NextIterationMap = isl::map::universe(MapSpace); 2909 for (unsigned u = 0; u < NextIterationMap.dim(isl::dim::in); u++) 2910 if (u != Dim) 2911 NextIterationMap = 2912 NextIterationMap.equate(isl::dim::in, u, isl::dim::out, u); 2913 isl::constraint C = 2914 isl::constraint::alloc_equality(isl::local_space(MapSpace)); 2915 C = C.set_constant_si(1); 2916 C = C.set_coefficient_si(isl::dim::in, Dim, 1); 2917 C = C.set_coefficient_si(isl::dim::out, Dim, -1); 2918 NextIterationMap = NextIterationMap.add_constraint(C); 2919 return NextIterationMap; 2920 } 2921 2922 bool Scop::addLoopBoundsToHeaderDomain( 2923 Loop *L, LoopInfo &LI, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { 2924 int LoopDepth = getRelativeLoopDepth(L); 2925 assert(LoopDepth >= 0 && "Loop in region should have at least depth one"); 2926 2927 BasicBlock *HeaderBB = L->getHeader(); 2928 assert(DomainMap.count(HeaderBB)); 2929 isl::set &HeaderBBDom = DomainMap[HeaderBB]; 2930 2931 isl::map NextIterationMap = 2932 createNextIterationMap(HeaderBBDom.get_space(), LoopDepth); 2933 2934 isl::set UnionBackedgeCondition = HeaderBBDom.empty(HeaderBBDom.get_space()); 2935 2936 SmallVector<BasicBlock *, 4> LatchBlocks; 2937 L->getLoopLatches(LatchBlocks); 2938 2939 for (BasicBlock *LatchBB : LatchBlocks) { 2940 // If the latch is only reachable via error statements we skip it. 2941 isl::set LatchBBDom = DomainMap.lookup(LatchBB); 2942 if (!LatchBBDom) 2943 continue; 2944 2945 isl::set BackedgeCondition = nullptr; 2946 2947 Instruction *TI = LatchBB->getTerminator(); 2948 BranchInst *BI = dyn_cast<BranchInst>(TI); 2949 assert(BI && "Only branch instructions allowed in loop latches"); 2950 2951 if (BI->isUnconditional()) 2952 BackedgeCondition = LatchBBDom; 2953 else { 2954 SmallVector<isl_set *, 8> ConditionSets; 2955 int idx = BI->getSuccessor(0) != HeaderBB; 2956 if (!buildConditionSets(*this, LatchBB, TI, L, LatchBBDom.get(), 2957 InvalidDomainMap, ConditionSets)) 2958 return false; 2959 2960 // Free the non back edge condition set as we do not need it. 2961 isl_set_free(ConditionSets[1 - idx]); 2962 2963 BackedgeCondition = isl::manage(ConditionSets[idx]); 2964 } 2965 2966 int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB)); 2967 assert(LatchLoopDepth >= LoopDepth); 2968 BackedgeCondition = BackedgeCondition.project_out( 2969 isl::dim::set, LoopDepth + 1, LatchLoopDepth - LoopDepth); 2970 UnionBackedgeCondition = UnionBackedgeCondition.unite(BackedgeCondition); 2971 } 2972 2973 isl::map ForwardMap = ForwardMap.lex_le(HeaderBBDom.get_space()); 2974 for (int i = 0; i < LoopDepth; i++) 2975 ForwardMap = ForwardMap.equate(isl::dim::in, i, isl::dim::out, i); 2976 2977 isl::set UnionBackedgeConditionComplement = 2978 UnionBackedgeCondition.complement(); 2979 UnionBackedgeConditionComplement = 2980 UnionBackedgeConditionComplement.lower_bound_si(isl::dim::set, LoopDepth, 2981 0); 2982 UnionBackedgeConditionComplement = 2983 UnionBackedgeConditionComplement.apply(ForwardMap); 2984 HeaderBBDom = HeaderBBDom.subtract(UnionBackedgeConditionComplement); 2985 HeaderBBDom = HeaderBBDom.apply(NextIterationMap); 2986 2987 auto Parts = partitionSetParts(HeaderBBDom, LoopDepth); 2988 HeaderBBDom = Parts.second; 2989 2990 // Check if there is a <nsw> tagged AddRec for this loop and if so do not add 2991 // the bounded assumptions to the context as they are already implied by the 2992 // <nsw> tag. 2993 if (Affinator.hasNSWAddRecForLoop(L)) 2994 return true; 2995 2996 isl::set UnboundedCtx = Parts.first.params(); 2997 recordAssumption(INFINITELOOP, UnboundedCtx, 2998 HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION); 2999 return true; 3000 } 3001 3002 MemoryAccess *Scop::lookupBasePtrAccess(MemoryAccess *MA) { 3003 Value *PointerBase = MA->getOriginalBaseAddr(); 3004 3005 auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase); 3006 if (!PointerBaseInst) 3007 return nullptr; 3008 3009 auto *BasePtrStmt = getStmtFor(PointerBaseInst); 3010 if (!BasePtrStmt) 3011 return nullptr; 3012 3013 return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst); 3014 } 3015 3016 bool Scop::hasNonHoistableBasePtrInScop(MemoryAccess *MA, 3017 isl::union_map Writes) { 3018 if (auto *BasePtrMA = lookupBasePtrAccess(MA)) { 3019 return getNonHoistableCtx(BasePtrMA, Writes).is_null(); 3020 } 3021 3022 Value *BaseAddr = MA->getOriginalBaseAddr(); 3023 if (auto *BasePtrInst = dyn_cast<Instruction>(BaseAddr)) 3024 if (!isa<LoadInst>(BasePtrInst)) 3025 return contains(BasePtrInst); 3026 3027 return false; 3028 } 3029 3030 bool Scop::buildAliasChecks(AliasAnalysis &AA) { 3031 if (!PollyUseRuntimeAliasChecks) 3032 return true; 3033 3034 if (buildAliasGroups(AA)) { 3035 // Aliasing assumptions do not go through addAssumption but we still want to 3036 // collect statistics so we do it here explicitly. 3037 if (MinMaxAliasGroups.size()) 3038 AssumptionsAliasing++; 3039 return true; 3040 } 3041 3042 // If a problem occurs while building the alias groups we need to delete 3043 // this SCoP and pretend it wasn't valid in the first place. To this end 3044 // we make the assumed context infeasible. 3045 invalidate(ALIASING, DebugLoc()); 3046 3047 LLVM_DEBUG( 3048 dbgs() << "\n\nNOTE: Run time checks for " << getNameStr() 3049 << " could not be created as the number of parameters involved " 3050 "is too high. The SCoP will be " 3051 "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust " 3052 "the maximal number of parameters but be advised that the " 3053 "compile time might increase exponentially.\n\n"); 3054 return false; 3055 } 3056 3057 std::tuple<Scop::AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>> 3058 Scop::buildAliasGroupsForAccesses(AliasAnalysis &AA) { 3059 AliasSetTracker AST(AA); 3060 3061 DenseMap<Value *, MemoryAccess *> PtrToAcc; 3062 DenseSet<const ScopArrayInfo *> HasWriteAccess; 3063 for (ScopStmt &Stmt : *this) { 3064 3065 isl::set StmtDomain = Stmt.getDomain(); 3066 bool StmtDomainEmpty = StmtDomain.is_empty(); 3067 3068 // Statements with an empty domain will never be executed. 3069 if (StmtDomainEmpty) 3070 continue; 3071 3072 for (MemoryAccess *MA : Stmt) { 3073 if (MA->isScalarKind()) 3074 continue; 3075 if (!MA->isRead()) 3076 HasWriteAccess.insert(MA->getScopArrayInfo()); 3077 MemAccInst Acc(MA->getAccessInstruction()); 3078 if (MA->isRead() && isa<MemTransferInst>(Acc)) 3079 PtrToAcc[cast<MemTransferInst>(Acc)->getRawSource()] = MA; 3080 else 3081 PtrToAcc[Acc.getPointerOperand()] = MA; 3082 AST.add(Acc); 3083 } 3084 } 3085 3086 AliasGroupVectorTy AliasGroups; 3087 for (AliasSet &AS : AST) { 3088 if (AS.isMustAlias() || AS.isForwardingAliasSet()) 3089 continue; 3090 AliasGroupTy AG; 3091 for (auto &PR : AS) 3092 AG.push_back(PtrToAcc[PR.getValue()]); 3093 if (AG.size() < 2) 3094 continue; 3095 AliasGroups.push_back(std::move(AG)); 3096 } 3097 3098 return std::make_tuple(AliasGroups, HasWriteAccess); 3099 } 3100 3101 void Scop::splitAliasGroupsByDomain(AliasGroupVectorTy &AliasGroups) { 3102 for (unsigned u = 0; u < AliasGroups.size(); u++) { 3103 AliasGroupTy NewAG; 3104 AliasGroupTy &AG = AliasGroups[u]; 3105 AliasGroupTy::iterator AGI = AG.begin(); 3106 isl::set AGDomain = getAccessDomain(*AGI); 3107 while (AGI != AG.end()) { 3108 MemoryAccess *MA = *AGI; 3109 isl::set MADomain = getAccessDomain(MA); 3110 if (AGDomain.is_disjoint(MADomain)) { 3111 NewAG.push_back(MA); 3112 AGI = AG.erase(AGI); 3113 } else { 3114 AGDomain = AGDomain.unite(MADomain); 3115 AGI++; 3116 } 3117 } 3118 if (NewAG.size() > 1) 3119 AliasGroups.push_back(std::move(NewAG)); 3120 } 3121 } 3122 3123 bool Scop::buildAliasGroups(AliasAnalysis &AA) { 3124 // To create sound alias checks we perform the following steps: 3125 // o) We partition each group into read only and non read only accesses. 3126 // o) For each group with more than one base pointer we then compute minimal 3127 // and maximal accesses to each array of a group in read only and non 3128 // read only partitions separately. 3129 AliasGroupVectorTy AliasGroups; 3130 DenseSet<const ScopArrayInfo *> HasWriteAccess; 3131 3132 std::tie(AliasGroups, HasWriteAccess) = buildAliasGroupsForAccesses(AA); 3133 3134 splitAliasGroupsByDomain(AliasGroups); 3135 3136 for (AliasGroupTy &AG : AliasGroups) { 3137 if (!hasFeasibleRuntimeContext()) 3138 return false; 3139 3140 { 3141 IslMaxOperationsGuard MaxOpGuard(getIslCtx().get(), OptComputeOut); 3142 bool Valid = buildAliasGroup(AG, HasWriteAccess); 3143 if (!Valid) 3144 return false; 3145 } 3146 if (isl_ctx_last_error(getIslCtx().get()) == isl_error_quota) { 3147 invalidate(COMPLEXITY, DebugLoc()); 3148 return false; 3149 } 3150 } 3151 3152 return true; 3153 } 3154 3155 bool Scop::buildAliasGroup(Scop::AliasGroupTy &AliasGroup, 3156 DenseSet<const ScopArrayInfo *> HasWriteAccess) { 3157 AliasGroupTy ReadOnlyAccesses; 3158 AliasGroupTy ReadWriteAccesses; 3159 SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays; 3160 SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays; 3161 3162 if (AliasGroup.size() < 2) 3163 return true; 3164 3165 for (MemoryAccess *Access : AliasGroup) { 3166 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "PossibleAlias", 3167 Access->getAccessInstruction()) 3168 << "Possibly aliasing pointer, use restrict keyword."); 3169 const ScopArrayInfo *Array = Access->getScopArrayInfo(); 3170 if (HasWriteAccess.count(Array)) { 3171 ReadWriteArrays.insert(Array); 3172 ReadWriteAccesses.push_back(Access); 3173 } else { 3174 ReadOnlyArrays.insert(Array); 3175 ReadOnlyAccesses.push_back(Access); 3176 } 3177 } 3178 3179 // If there are no read-only pointers, and less than two read-write pointers, 3180 // no alias check is needed. 3181 if (ReadOnlyAccesses.empty() && ReadWriteArrays.size() <= 1) 3182 return true; 3183 3184 // If there is no read-write pointer, no alias check is needed. 3185 if (ReadWriteArrays.empty()) 3186 return true; 3187 3188 // For non-affine accesses, no alias check can be generated as we cannot 3189 // compute a sufficiently tight lower and upper bound: bail out. 3190 for (MemoryAccess *MA : AliasGroup) { 3191 if (!MA->isAffine()) { 3192 invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc(), 3193 MA->getAccessInstruction()->getParent()); 3194 return false; 3195 } 3196 } 3197 3198 // Ensure that for all memory accesses for which we generate alias checks, 3199 // their base pointers are available. 3200 for (MemoryAccess *MA : AliasGroup) { 3201 if (MemoryAccess *BasePtrMA = lookupBasePtrAccess(MA)) 3202 addRequiredInvariantLoad( 3203 cast<LoadInst>(BasePtrMA->getAccessInstruction())); 3204 } 3205 3206 MinMaxAliasGroups.emplace_back(); 3207 MinMaxVectorPairTy &pair = MinMaxAliasGroups.back(); 3208 MinMaxVectorTy &MinMaxAccessesReadWrite = pair.first; 3209 MinMaxVectorTy &MinMaxAccessesReadOnly = pair.second; 3210 3211 bool Valid; 3212 3213 Valid = 3214 calculateMinMaxAccess(ReadWriteAccesses, *this, MinMaxAccessesReadWrite); 3215 3216 if (!Valid) 3217 return false; 3218 3219 // Bail out if the number of values we need to compare is too large. 3220 // This is important as the number of comparisons grows quadratically with 3221 // the number of values we need to compare. 3222 if (MinMaxAccessesReadWrite.size() + ReadOnlyArrays.size() > 3223 RunTimeChecksMaxArraysPerGroup) 3224 return false; 3225 3226 Valid = 3227 calculateMinMaxAccess(ReadOnlyAccesses, *this, MinMaxAccessesReadOnly); 3228 3229 if (!Valid) 3230 return false; 3231 3232 return true; 3233 } 3234 3235 /// Get the smallest loop that contains @p S but is not in @p S. 3236 static Loop *getLoopSurroundingScop(Scop &S, LoopInfo &LI) { 3237 // Start with the smallest loop containing the entry and expand that 3238 // loop until it contains all blocks in the region. If there is a loop 3239 // containing all blocks in the region check if it is itself contained 3240 // and if so take the parent loop as it will be the smallest containing 3241 // the region but not contained by it. 3242 Loop *L = LI.getLoopFor(S.getEntry()); 3243 while (L) { 3244 bool AllContained = true; 3245 for (auto *BB : S.blocks()) 3246 AllContained &= L->contains(BB); 3247 if (AllContained) 3248 break; 3249 L = L->getParentLoop(); 3250 } 3251 3252 return L ? (S.contains(L) ? L->getParentLoop() : L) : nullptr; 3253 } 3254 3255 int Scop::NextScopID = 0; 3256 3257 std::string Scop::CurrentFunc; 3258 3259 int Scop::getNextID(std::string ParentFunc) { 3260 if (ParentFunc != CurrentFunc) { 3261 CurrentFunc = ParentFunc; 3262 NextScopID = 0; 3263 } 3264 return NextScopID++; 3265 } 3266 3267 Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI, 3268 DominatorTree &DT, ScopDetection::DetectionContext &DC, 3269 OptimizationRemarkEmitter &ORE) 3270 : IslCtx(isl_ctx_alloc(), isl_ctx_free), SE(&ScalarEvolution), DT(&DT), 3271 R(R), name(None), HasSingleExitEdge(R.getExitingBlock()), DC(DC), 3272 ORE(ORE), Affinator(this, LI), 3273 ID(getNextID((*R.getEntry()->getParent()).getName().str())) { 3274 if (IslOnErrorAbort) 3275 isl_options_set_on_error(getIslCtx().get(), ISL_ON_ERROR_ABORT); 3276 buildContext(); 3277 } 3278 3279 Scop::~Scop() = default; 3280 3281 void Scop::foldSizeConstantsToRight() { 3282 isl::union_set Accessed = getAccesses().range(); 3283 3284 for (auto Array : arrays()) { 3285 if (Array->getNumberOfDimensions() <= 1) 3286 continue; 3287 3288 isl::space Space = Array->getSpace(); 3289 Space = Space.align_params(Accessed.get_space()); 3290 3291 if (!Accessed.contains(Space)) 3292 continue; 3293 3294 isl::set Elements = Accessed.extract_set(Space); 3295 isl::map Transform = isl::map::universe(Array->getSpace().map_from_set()); 3296 3297 std::vector<int> Int; 3298 int Dims = Elements.dim(isl::dim::set); 3299 for (int i = 0; i < Dims; i++) { 3300 isl::set DimOnly = isl::set(Elements).project_out(isl::dim::set, 0, i); 3301 DimOnly = DimOnly.project_out(isl::dim::set, 1, Dims - i - 1); 3302 DimOnly = DimOnly.lower_bound_si(isl::dim::set, 0, 0); 3303 3304 isl::basic_set DimHull = DimOnly.affine_hull(); 3305 3306 if (i == Dims - 1) { 3307 Int.push_back(1); 3308 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i); 3309 continue; 3310 } 3311 3312 if (DimHull.dim(isl::dim::div) == 1) { 3313 isl::aff Diff = DimHull.get_div(0); 3314 isl::val Val = Diff.get_denominator_val(); 3315 3316 int ValInt = 1; 3317 if (Val.is_int()) { 3318 auto ValAPInt = APIntFromVal(Val); 3319 if (ValAPInt.isSignedIntN(32)) 3320 ValInt = ValAPInt.getSExtValue(); 3321 } else { 3322 } 3323 3324 Int.push_back(ValInt); 3325 isl::constraint C = isl::constraint::alloc_equality( 3326 isl::local_space(Transform.get_space())); 3327 C = C.set_coefficient_si(isl::dim::out, i, ValInt); 3328 C = C.set_coefficient_si(isl::dim::in, i, -1); 3329 Transform = Transform.add_constraint(C); 3330 continue; 3331 } 3332 3333 isl::basic_set ZeroSet = isl::basic_set(DimHull); 3334 ZeroSet = ZeroSet.fix_si(isl::dim::set, 0, 0); 3335 3336 int ValInt = 1; 3337 if (ZeroSet.is_equal(DimHull)) { 3338 ValInt = 0; 3339 } 3340 3341 Int.push_back(ValInt); 3342 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i); 3343 } 3344 3345 isl::set MappedElements = isl::map(Transform).domain(); 3346 if (!Elements.is_subset(MappedElements)) 3347 continue; 3348 3349 bool CanFold = true; 3350 if (Int[0] <= 1) 3351 CanFold = false; 3352 3353 unsigned NumDims = Array->getNumberOfDimensions(); 3354 for (unsigned i = 1; i < NumDims - 1; i++) 3355 if (Int[0] != Int[i] && Int[i]) 3356 CanFold = false; 3357 3358 if (!CanFold) 3359 continue; 3360 3361 for (auto &Access : AccessFunctions) 3362 if (Access->getScopArrayInfo() == Array) 3363 Access->setAccessRelation( 3364 Access->getAccessRelation().apply_range(Transform)); 3365 3366 std::vector<const SCEV *> Sizes; 3367 for (unsigned i = 0; i < NumDims; i++) { 3368 auto Size = Array->getDimensionSize(i); 3369 3370 if (i == NumDims - 1) 3371 Size = SE->getMulExpr(Size, SE->getConstant(Size->getType(), Int[0])); 3372 Sizes.push_back(Size); 3373 } 3374 3375 Array->updateSizes(Sizes, false /* CheckConsistency */); 3376 } 3377 } 3378 3379 void Scop::markFortranArrays() { 3380 for (ScopStmt &Stmt : Stmts) { 3381 for (MemoryAccess *MemAcc : Stmt) { 3382 Value *FAD = MemAcc->getFortranArrayDescriptor(); 3383 if (!FAD) 3384 continue; 3385 3386 // TODO: const_cast-ing to edit 3387 ScopArrayInfo *SAI = 3388 const_cast<ScopArrayInfo *>(MemAcc->getLatestScopArrayInfo()); 3389 assert(SAI && "memory access into a Fortran array does not " 3390 "have an associated ScopArrayInfo"); 3391 SAI->applyAndSetFAD(FAD); 3392 } 3393 } 3394 } 3395 3396 void Scop::finalizeAccesses() { 3397 updateAccessDimensionality(); 3398 foldSizeConstantsToRight(); 3399 foldAccessRelations(); 3400 assumeNoOutOfBounds(); 3401 markFortranArrays(); 3402 } 3403 3404 void Scop::updateAccessDimensionality() { 3405 // Check all array accesses for each base pointer and find a (virtual) element 3406 // size for the base pointer that divides all access functions. 3407 for (ScopStmt &Stmt : *this) 3408 for (MemoryAccess *Access : Stmt) { 3409 if (!Access->isArrayKind()) 3410 continue; 3411 ScopArrayInfo *Array = 3412 const_cast<ScopArrayInfo *>(Access->getScopArrayInfo()); 3413 3414 if (Array->getNumberOfDimensions() != 1) 3415 continue; 3416 unsigned DivisibleSize = Array->getElemSizeInBytes(); 3417 const SCEV *Subscript = Access->getSubscript(0); 3418 while (!isDivisible(Subscript, DivisibleSize, *SE)) 3419 DivisibleSize /= 2; 3420 auto *Ty = IntegerType::get(SE->getContext(), DivisibleSize * 8); 3421 Array->updateElementType(Ty); 3422 } 3423 3424 for (auto &Stmt : *this) 3425 for (auto &Access : Stmt) 3426 Access->updateDimensionality(); 3427 } 3428 3429 void Scop::foldAccessRelations() { 3430 for (auto &Stmt : *this) 3431 for (auto &Access : Stmt) 3432 Access->foldAccessRelation(); 3433 } 3434 3435 void Scop::assumeNoOutOfBounds() { 3436 for (auto &Stmt : *this) 3437 for (auto &Access : Stmt) 3438 Access->assumeNoOutOfBound(); 3439 } 3440 3441 void Scop::removeFromStmtMap(ScopStmt &Stmt) { 3442 for (Instruction *Inst : Stmt.getInstructions()) 3443 InstStmtMap.erase(Inst); 3444 3445 if (Stmt.isRegionStmt()) { 3446 for (BasicBlock *BB : Stmt.getRegion()->blocks()) { 3447 StmtMap.erase(BB); 3448 // Skip entry basic block, as its instructions are already deleted as 3449 // part of the statement's instruction list. 3450 if (BB == Stmt.getEntryBlock()) 3451 continue; 3452 for (Instruction &Inst : *BB) 3453 InstStmtMap.erase(&Inst); 3454 } 3455 } else { 3456 auto StmtMapIt = StmtMap.find(Stmt.getBasicBlock()); 3457 if (StmtMapIt != StmtMap.end()) 3458 StmtMapIt->second.erase(std::remove(StmtMapIt->second.begin(), 3459 StmtMapIt->second.end(), &Stmt), 3460 StmtMapIt->second.end()); 3461 for (Instruction *Inst : Stmt.getInstructions()) 3462 InstStmtMap.erase(Inst); 3463 } 3464 } 3465 3466 void Scop::removeStmts(std::function<bool(ScopStmt &)> ShouldDelete, 3467 bool AfterHoisting) { 3468 for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) { 3469 if (!ShouldDelete(*StmtIt)) { 3470 StmtIt++; 3471 continue; 3472 } 3473 3474 // Start with removing all of the statement's accesses including erasing it 3475 // from all maps that are pointing to them. 3476 // Make a temporary copy because removing MAs invalidates the iterator. 3477 SmallVector<MemoryAccess *, 16> MAList(StmtIt->begin(), StmtIt->end()); 3478 for (MemoryAccess *MA : MAList) 3479 StmtIt->removeSingleMemoryAccess(MA, AfterHoisting); 3480 3481 removeFromStmtMap(*StmtIt); 3482 StmtIt = Stmts.erase(StmtIt); 3483 } 3484 } 3485 3486 void Scop::removeStmtNotInDomainMap() { 3487 auto ShouldDelete = [this](ScopStmt &Stmt) -> bool { 3488 isl::set Domain = DomainMap.lookup(Stmt.getEntryBlock()); 3489 if (!Domain) 3490 return true; 3491 return Domain.is_empty(); 3492 }; 3493 removeStmts(ShouldDelete, false); 3494 } 3495 3496 void Scop::simplifySCoP(bool AfterHoisting) { 3497 auto ShouldDelete = [AfterHoisting](ScopStmt &Stmt) -> bool { 3498 // Never delete statements that contain calls to debug functions. 3499 if (hasDebugCall(&Stmt)) 3500 return false; 3501 3502 bool RemoveStmt = Stmt.isEmpty(); 3503 3504 // Remove read only statements only after invariant load hoisting. 3505 if (!RemoveStmt && AfterHoisting) { 3506 bool OnlyRead = true; 3507 for (MemoryAccess *MA : Stmt) { 3508 if (MA->isRead()) 3509 continue; 3510 3511 OnlyRead = false; 3512 break; 3513 } 3514 3515 RemoveStmt = OnlyRead; 3516 } 3517 return RemoveStmt; 3518 }; 3519 3520 removeStmts(ShouldDelete, AfterHoisting); 3521 } 3522 3523 InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) { 3524 LoadInst *LInst = dyn_cast<LoadInst>(Val); 3525 if (!LInst) 3526 return nullptr; 3527 3528 if (Value *Rep = InvEquivClassVMap.lookup(LInst)) 3529 LInst = cast<LoadInst>(Rep); 3530 3531 Type *Ty = LInst->getType(); 3532 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 3533 for (auto &IAClass : InvariantEquivClasses) { 3534 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType) 3535 continue; 3536 3537 auto &MAs = IAClass.InvariantAccesses; 3538 for (auto *MA : MAs) 3539 if (MA->getAccessInstruction() == Val) 3540 return &IAClass; 3541 } 3542 3543 return nullptr; 3544 } 3545 3546 bool isAParameter(llvm::Value *maybeParam, const Function &F) { 3547 for (const llvm::Argument &Arg : F.args()) 3548 if (&Arg == maybeParam) 3549 return true; 3550 3551 return false; 3552 } 3553 3554 bool Scop::canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty, 3555 bool MAInvalidCtxIsEmpty, 3556 bool NonHoistableCtxIsEmpty) { 3557 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction()); 3558 const DataLayout &DL = LInst->getParent()->getModule()->getDataLayout(); 3559 if (PollyAllowDereferenceOfAllFunctionParams && 3560 isAParameter(LInst->getPointerOperand(), getFunction())) 3561 return true; 3562 3563 // TODO: We can provide more information for better but more expensive 3564 // results. 3565 if (!isDereferenceableAndAlignedPointer(LInst->getPointerOperand(), 3566 LInst->getAlignment(), DL)) 3567 return false; 3568 3569 // If the location might be overwritten we do not hoist it unconditionally. 3570 // 3571 // TODO: This is probably too conservative. 3572 if (!NonHoistableCtxIsEmpty) 3573 return false; 3574 3575 // If a dereferenceable load is in a statement that is modeled precisely we 3576 // can hoist it. 3577 if (StmtInvalidCtxIsEmpty && MAInvalidCtxIsEmpty) 3578 return true; 3579 3580 // Even if the statement is not modeled precisely we can hoist the load if it 3581 // does not involve any parameters that might have been specialized by the 3582 // statement domain. 3583 for (unsigned u = 0, e = MA->getNumSubscripts(); u < e; u++) 3584 if (!isa<SCEVConstant>(MA->getSubscript(u))) 3585 return false; 3586 return true; 3587 } 3588 3589 void Scop::addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs) { 3590 if (InvMAs.empty()) 3591 return; 3592 3593 isl::set StmtInvalidCtx = Stmt.getInvalidContext(); 3594 bool StmtInvalidCtxIsEmpty = StmtInvalidCtx.is_empty(); 3595 3596 // Get the context under which the statement is executed but remove the error 3597 // context under which this statement is reached. 3598 isl::set DomainCtx = Stmt.getDomain().params(); 3599 DomainCtx = DomainCtx.subtract(StmtInvalidCtx); 3600 3601 if (DomainCtx.n_basic_set() >= MaxDisjunctsInDomain) { 3602 auto *AccInst = InvMAs.front().MA->getAccessInstruction(); 3603 invalidate(COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent()); 3604 return; 3605 } 3606 3607 // Project out all parameters that relate to loads in the statement. Otherwise 3608 // we could have cyclic dependences on the constraints under which the 3609 // hoisted loads are executed and we could not determine an order in which to 3610 // pre-load them. This happens because not only lower bounds are part of the 3611 // domain but also upper bounds. 3612 for (auto &InvMA : InvMAs) { 3613 auto *MA = InvMA.MA; 3614 Instruction *AccInst = MA->getAccessInstruction(); 3615 if (SE->isSCEVable(AccInst->getType())) { 3616 SetVector<Value *> Values; 3617 for (const SCEV *Parameter : Parameters) { 3618 Values.clear(); 3619 findValues(Parameter, *SE, Values); 3620 if (!Values.count(AccInst)) 3621 continue; 3622 3623 if (isl::id ParamId = getIdForParam(Parameter)) { 3624 int Dim = DomainCtx.find_dim_by_id(isl::dim::param, ParamId); 3625 if (Dim >= 0) 3626 DomainCtx = DomainCtx.eliminate(isl::dim::param, Dim, 1); 3627 } 3628 } 3629 } 3630 } 3631 3632 for (auto &InvMA : InvMAs) { 3633 auto *MA = InvMA.MA; 3634 isl::set NHCtx = InvMA.NonHoistableCtx; 3635 3636 // Check for another invariant access that accesses the same location as 3637 // MA and if found consolidate them. Otherwise create a new equivalence 3638 // class at the end of InvariantEquivClasses. 3639 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction()); 3640 Type *Ty = LInst->getType(); 3641 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 3642 3643 isl::set MAInvalidCtx = MA->getInvalidContext(); 3644 bool NonHoistableCtxIsEmpty = NHCtx.is_empty(); 3645 bool MAInvalidCtxIsEmpty = MAInvalidCtx.is_empty(); 3646 3647 isl::set MACtx; 3648 // Check if we know that this pointer can be speculatively accessed. 3649 if (canAlwaysBeHoisted(MA, StmtInvalidCtxIsEmpty, MAInvalidCtxIsEmpty, 3650 NonHoistableCtxIsEmpty)) { 3651 MACtx = isl::set::universe(DomainCtx.get_space()); 3652 } else { 3653 MACtx = DomainCtx; 3654 MACtx = MACtx.subtract(MAInvalidCtx.unite(NHCtx)); 3655 MACtx = MACtx.gist_params(getContext()); 3656 } 3657 3658 bool Consolidated = false; 3659 for (auto &IAClass : InvariantEquivClasses) { 3660 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType) 3661 continue; 3662 3663 // If the pointer and the type is equal check if the access function wrt. 3664 // to the domain is equal too. It can happen that the domain fixes 3665 // parameter values and these can be different for distinct part of the 3666 // SCoP. If this happens we cannot consolidate the loads but need to 3667 // create a new invariant load equivalence class. 3668 auto &MAs = IAClass.InvariantAccesses; 3669 if (!MAs.empty()) { 3670 auto *LastMA = MAs.front(); 3671 3672 isl::set AR = MA->getAccessRelation().range(); 3673 isl::set LastAR = LastMA->getAccessRelation().range(); 3674 bool SameAR = AR.is_equal(LastAR); 3675 3676 if (!SameAR) 3677 continue; 3678 } 3679 3680 // Add MA to the list of accesses that are in this class. 3681 MAs.push_front(MA); 3682 3683 Consolidated = true; 3684 3685 // Unify the execution context of the class and this statement. 3686 isl::set IAClassDomainCtx = IAClass.ExecutionContext; 3687 if (IAClassDomainCtx) 3688 IAClassDomainCtx = IAClassDomainCtx.unite(MACtx).coalesce(); 3689 else 3690 IAClassDomainCtx = MACtx; 3691 IAClass.ExecutionContext = IAClassDomainCtx; 3692 break; 3693 } 3694 3695 if (Consolidated) 3696 continue; 3697 3698 MACtx = MACtx.coalesce(); 3699 3700 // If we did not consolidate MA, thus did not find an equivalence class 3701 // for it, we create a new one. 3702 InvariantEquivClasses.emplace_back( 3703 InvariantEquivClassTy{PointerSCEV, MemoryAccessList{MA}, MACtx, Ty}); 3704 } 3705 } 3706 3707 /// Check if an access range is too complex. 3708 /// 3709 /// An access range is too complex, if it contains either many disjuncts or 3710 /// very complex expressions. As a simple heuristic, we assume if a set to 3711 /// be too complex if the sum of existentially quantified dimensions and 3712 /// set dimensions is larger than a threshold. This reliably detects both 3713 /// sets with many disjuncts as well as sets with many divisions as they 3714 /// arise in h264. 3715 /// 3716 /// @param AccessRange The range to check for complexity. 3717 /// 3718 /// @returns True if the access range is too complex. 3719 static bool isAccessRangeTooComplex(isl::set AccessRange) { 3720 unsigned NumTotalDims = 0; 3721 3722 for (isl::basic_set BSet : AccessRange.get_basic_set_list()) { 3723 NumTotalDims += BSet.dim(isl::dim::div); 3724 NumTotalDims += BSet.dim(isl::dim::set); 3725 } 3726 3727 if (NumTotalDims > MaxDimensionsInAccessRange) 3728 return true; 3729 3730 return false; 3731 } 3732 3733 isl::set Scop::getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes) { 3734 // TODO: Loads that are not loop carried, hence are in a statement with 3735 // zero iterators, are by construction invariant, though we 3736 // currently "hoist" them anyway. This is necessary because we allow 3737 // them to be treated as parameters (e.g., in conditions) and our code 3738 // generation would otherwise use the old value. 3739 3740 auto &Stmt = *Access->getStatement(); 3741 BasicBlock *BB = Stmt.getEntryBlock(); 3742 3743 if (Access->isScalarKind() || Access->isWrite() || !Access->isAffine() || 3744 Access->isMemoryIntrinsic()) 3745 return nullptr; 3746 3747 // Skip accesses that have an invariant base pointer which is defined but 3748 // not loaded inside the SCoP. This can happened e.g., if a readnone call 3749 // returns a pointer that is used as a base address. However, as we want 3750 // to hoist indirect pointers, we allow the base pointer to be defined in 3751 // the region if it is also a memory access. Each ScopArrayInfo object 3752 // that has a base pointer origin has a base pointer that is loaded and 3753 // that it is invariant, thus it will be hoisted too. However, if there is 3754 // no base pointer origin we check that the base pointer is defined 3755 // outside the region. 3756 auto *LI = cast<LoadInst>(Access->getAccessInstruction()); 3757 if (hasNonHoistableBasePtrInScop(Access, Writes)) 3758 return nullptr; 3759 3760 isl::map AccessRelation = Access->getAccessRelation(); 3761 assert(!AccessRelation.is_empty()); 3762 3763 if (AccessRelation.involves_dims(isl::dim::in, 0, Stmt.getNumIterators())) 3764 return nullptr; 3765 3766 AccessRelation = AccessRelation.intersect_domain(Stmt.getDomain()); 3767 isl::set SafeToLoad; 3768 3769 auto &DL = getFunction().getParent()->getDataLayout(); 3770 if (isSafeToLoadUnconditionally(LI->getPointerOperand(), LI->getAlignment(), 3771 DL)) { 3772 SafeToLoad = isl::set::universe(AccessRelation.get_space().range()); 3773 } else if (BB != LI->getParent()) { 3774 // Skip accesses in non-affine subregions as they might not be executed 3775 // under the same condition as the entry of the non-affine subregion. 3776 return nullptr; 3777 } else { 3778 SafeToLoad = AccessRelation.range(); 3779 } 3780 3781 if (isAccessRangeTooComplex(AccessRelation.range())) 3782 return nullptr; 3783 3784 isl::union_map Written = Writes.intersect_range(SafeToLoad); 3785 isl::set WrittenCtx = Written.params(); 3786 bool IsWritten = !WrittenCtx.is_empty(); 3787 3788 if (!IsWritten) 3789 return WrittenCtx; 3790 3791 WrittenCtx = WrittenCtx.remove_divs(); 3792 bool TooComplex = WrittenCtx.n_basic_set() >= MaxDisjunctsInDomain; 3793 if (TooComplex || !isRequiredInvariantLoad(LI)) 3794 return nullptr; 3795 3796 addAssumption(INVARIANTLOAD, WrittenCtx, LI->getDebugLoc(), AS_RESTRICTION, 3797 LI->getParent()); 3798 return WrittenCtx; 3799 } 3800 3801 void Scop::verifyInvariantLoads() { 3802 auto &RIL = getRequiredInvariantLoads(); 3803 for (LoadInst *LI : RIL) { 3804 assert(LI && contains(LI)); 3805 // If there exists a statement in the scop which has a memory access for 3806 // @p LI, then mark this scop as infeasible for optimization. 3807 for (ScopStmt &Stmt : Stmts) 3808 if (Stmt.getArrayAccessOrNULLFor(LI)) { 3809 invalidate(INVARIANTLOAD, LI->getDebugLoc(), LI->getParent()); 3810 return; 3811 } 3812 } 3813 } 3814 3815 void Scop::hoistInvariantLoads() { 3816 if (!PollyInvariantLoadHoisting) 3817 return; 3818 3819 isl::union_map Writes = getWrites(); 3820 for (ScopStmt &Stmt : *this) { 3821 InvariantAccessesTy InvariantAccesses; 3822 3823 for (MemoryAccess *Access : Stmt) 3824 if (isl::set NHCtx = getNonHoistableCtx(Access, Writes)) 3825 InvariantAccesses.push_back({Access, NHCtx}); 3826 3827 // Transfer the memory access from the statement to the SCoP. 3828 for (auto InvMA : InvariantAccesses) 3829 Stmt.removeMemoryAccess(InvMA.MA); 3830 addInvariantLoads(Stmt, InvariantAccesses); 3831 } 3832 } 3833 3834 /// Find the canonical scop array info object for a set of invariant load 3835 /// hoisted loads. The canonical array is the one that corresponds to the 3836 /// first load in the list of accesses which is used as base pointer of a 3837 /// scop array. 3838 static const ScopArrayInfo *findCanonicalArray(Scop *S, 3839 MemoryAccessList &Accesses) { 3840 for (MemoryAccess *Access : Accesses) { 3841 const ScopArrayInfo *CanonicalArray = S->getScopArrayInfoOrNull( 3842 Access->getAccessInstruction(), MemoryKind::Array); 3843 if (CanonicalArray) 3844 return CanonicalArray; 3845 } 3846 return nullptr; 3847 } 3848 3849 /// Check if @p Array severs as base array in an invariant load. 3850 static bool isUsedForIndirectHoistedLoad(Scop *S, const ScopArrayInfo *Array) { 3851 for (InvariantEquivClassTy &EqClass2 : S->getInvariantAccesses()) 3852 for (MemoryAccess *Access2 : EqClass2.InvariantAccesses) 3853 if (Access2->getScopArrayInfo() == Array) 3854 return true; 3855 return false; 3856 } 3857 3858 /// Replace the base pointer arrays in all memory accesses referencing @p Old, 3859 /// with a reference to @p New. 3860 static void replaceBasePtrArrays(Scop *S, const ScopArrayInfo *Old, 3861 const ScopArrayInfo *New) { 3862 for (ScopStmt &Stmt : *S) 3863 for (MemoryAccess *Access : Stmt) { 3864 if (Access->getLatestScopArrayInfo() != Old) 3865 continue; 3866 3867 isl::id Id = New->getBasePtrId(); 3868 isl::map Map = Access->getAccessRelation(); 3869 Map = Map.set_tuple_id(isl::dim::out, Id); 3870 Access->setAccessRelation(Map); 3871 } 3872 } 3873 3874 void Scop::canonicalizeDynamicBasePtrs() { 3875 for (InvariantEquivClassTy &EqClass : InvariantEquivClasses) { 3876 MemoryAccessList &BasePtrAccesses = EqClass.InvariantAccesses; 3877 3878 const ScopArrayInfo *CanonicalBasePtrSAI = 3879 findCanonicalArray(this, BasePtrAccesses); 3880 3881 if (!CanonicalBasePtrSAI) 3882 continue; 3883 3884 for (MemoryAccess *BasePtrAccess : BasePtrAccesses) { 3885 const ScopArrayInfo *BasePtrSAI = getScopArrayInfoOrNull( 3886 BasePtrAccess->getAccessInstruction(), MemoryKind::Array); 3887 if (!BasePtrSAI || BasePtrSAI == CanonicalBasePtrSAI || 3888 !BasePtrSAI->isCompatibleWith(CanonicalBasePtrSAI)) 3889 continue; 3890 3891 // we currently do not canonicalize arrays where some accesses are 3892 // hoisted as invariant loads. If we would, we need to update the access 3893 // function of the invariant loads as well. However, as this is not a 3894 // very common situation, we leave this for now to avoid further 3895 // complexity increases. 3896 if (isUsedForIndirectHoistedLoad(this, BasePtrSAI)) 3897 continue; 3898 3899 replaceBasePtrArrays(this, BasePtrSAI, CanonicalBasePtrSAI); 3900 } 3901 } 3902 } 3903 3904 ScopArrayInfo *Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, 3905 ArrayRef<const SCEV *> Sizes, 3906 MemoryKind Kind, 3907 const char *BaseName) { 3908 assert((BasePtr || BaseName) && 3909 "BasePtr and BaseName can not be nullptr at the same time."); 3910 assert(!(BasePtr && BaseName) && "BaseName is redundant."); 3911 auto &SAI = BasePtr ? ScopArrayInfoMap[std::make_pair(BasePtr, Kind)] 3912 : ScopArrayNameMap[BaseName]; 3913 if (!SAI) { 3914 auto &DL = getFunction().getParent()->getDataLayout(); 3915 SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind, 3916 DL, this, BaseName)); 3917 ScopArrayInfoSet.insert(SAI.get()); 3918 } else { 3919 SAI->updateElementType(ElementType); 3920 // In case of mismatching array sizes, we bail out by setting the run-time 3921 // context to false. 3922 if (!SAI->updateSizes(Sizes)) 3923 invalidate(DELINEARIZATION, DebugLoc()); 3924 } 3925 return SAI.get(); 3926 } 3927 3928 ScopArrayInfo *Scop::createScopArrayInfo(Type *ElementType, 3929 const std::string &BaseName, 3930 const std::vector<unsigned> &Sizes) { 3931 auto *DimSizeType = Type::getInt64Ty(getSE()->getContext()); 3932 std::vector<const SCEV *> SCEVSizes; 3933 3934 for (auto size : Sizes) 3935 if (size) 3936 SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false)); 3937 else 3938 SCEVSizes.push_back(nullptr); 3939 3940 auto *SAI = getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes, 3941 MemoryKind::Array, BaseName.c_str()); 3942 return SAI; 3943 } 3944 3945 const ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr, 3946 MemoryKind Kind) { 3947 auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get(); 3948 return SAI; 3949 } 3950 3951 const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) { 3952 auto *SAI = getScopArrayInfoOrNull(BasePtr, Kind); 3953 assert(SAI && "No ScopArrayInfo available for this base pointer"); 3954 return SAI; 3955 } 3956 3957 std::string Scop::getContextStr() const { return getContext().to_str(); } 3958 3959 std::string Scop::getAssumedContextStr() const { 3960 assert(AssumedContext && "Assumed context not yet built"); 3961 return AssumedContext.to_str(); 3962 } 3963 3964 std::string Scop::getInvalidContextStr() const { 3965 return InvalidContext.to_str(); 3966 } 3967 3968 std::string Scop::getNameStr() const { 3969 std::string ExitName, EntryName; 3970 std::tie(EntryName, ExitName) = getEntryExitStr(); 3971 return EntryName + "---" + ExitName; 3972 } 3973 3974 std::pair<std::string, std::string> Scop::getEntryExitStr() const { 3975 std::string ExitName, EntryName; 3976 raw_string_ostream ExitStr(ExitName); 3977 raw_string_ostream EntryStr(EntryName); 3978 3979 R.getEntry()->printAsOperand(EntryStr, false); 3980 EntryStr.str(); 3981 3982 if (R.getExit()) { 3983 R.getExit()->printAsOperand(ExitStr, false); 3984 ExitStr.str(); 3985 } else 3986 ExitName = "FunctionExit"; 3987 3988 return std::make_pair(EntryName, ExitName); 3989 } 3990 3991 isl::set Scop::getContext() const { return Context; } 3992 isl::space Scop::getParamSpace() const { return getContext().get_space(); } 3993 3994 isl::space Scop::getFullParamSpace() const { 3995 std::vector<isl::id> FortranIDs; 3996 FortranIDs = getFortranArrayIds(arrays()); 3997 3998 isl::space Space = isl::space::params_alloc( 3999 getIslCtx(), ParameterIds.size() + FortranIDs.size()); 4000 4001 unsigned PDim = 0; 4002 for (const SCEV *Parameter : Parameters) { 4003 isl::id Id = getIdForParam(Parameter); 4004 Space = Space.set_dim_id(isl::dim::param, PDim++, Id); 4005 } 4006 4007 for (isl::id Id : FortranIDs) 4008 Space = Space.set_dim_id(isl::dim::param, PDim++, Id); 4009 4010 return Space; 4011 } 4012 4013 isl::set Scop::getAssumedContext() const { 4014 assert(AssumedContext && "Assumed context not yet built"); 4015 return AssumedContext; 4016 } 4017 4018 bool Scop::isProfitable(bool ScalarsAreUnprofitable) const { 4019 if (PollyProcessUnprofitable) 4020 return true; 4021 4022 if (isEmpty()) 4023 return false; 4024 4025 unsigned OptimizableStmtsOrLoops = 0; 4026 for (auto &Stmt : *this) { 4027 if (Stmt.getNumIterators() == 0) 4028 continue; 4029 4030 bool ContainsArrayAccs = false; 4031 bool ContainsScalarAccs = false; 4032 for (auto *MA : Stmt) { 4033 if (MA->isRead()) 4034 continue; 4035 ContainsArrayAccs |= MA->isLatestArrayKind(); 4036 ContainsScalarAccs |= MA->isLatestScalarKind(); 4037 } 4038 4039 if (!ScalarsAreUnprofitable || (ContainsArrayAccs && !ContainsScalarAccs)) 4040 OptimizableStmtsOrLoops += Stmt.getNumIterators(); 4041 } 4042 4043 return OptimizableStmtsOrLoops > 1; 4044 } 4045 4046 bool Scop::hasFeasibleRuntimeContext() const { 4047 auto PositiveContext = getAssumedContext(); 4048 auto NegativeContext = getInvalidContext(); 4049 PositiveContext = addNonEmptyDomainConstraints(PositiveContext); 4050 // addNonEmptyDomainConstraints returns null if ScopStmts have a null domain 4051 if (!PositiveContext) 4052 return false; 4053 4054 bool IsFeasible = !(PositiveContext.is_empty() || 4055 PositiveContext.is_subset(NegativeContext)); 4056 if (!IsFeasible) 4057 return false; 4058 4059 auto DomainContext = getDomains().params(); 4060 IsFeasible = !DomainContext.is_subset(NegativeContext); 4061 IsFeasible &= !Context.is_subset(NegativeContext); 4062 4063 return IsFeasible; 4064 } 4065 4066 static std::string toString(AssumptionKind Kind) { 4067 switch (Kind) { 4068 case ALIASING: 4069 return "No-aliasing"; 4070 case INBOUNDS: 4071 return "Inbounds"; 4072 case WRAPPING: 4073 return "No-overflows"; 4074 case UNSIGNED: 4075 return "Signed-unsigned"; 4076 case COMPLEXITY: 4077 return "Low complexity"; 4078 case PROFITABLE: 4079 return "Profitable"; 4080 case ERRORBLOCK: 4081 return "No-error"; 4082 case INFINITELOOP: 4083 return "Finite loop"; 4084 case INVARIANTLOAD: 4085 return "Invariant load"; 4086 case DELINEARIZATION: 4087 return "Delinearization"; 4088 } 4089 llvm_unreachable("Unknown AssumptionKind!"); 4090 } 4091 4092 bool Scop::isEffectiveAssumption(isl::set Set, AssumptionSign Sign) { 4093 if (Sign == AS_ASSUMPTION) { 4094 if (Context.is_subset(Set)) 4095 return false; 4096 4097 if (AssumedContext.is_subset(Set)) 4098 return false; 4099 } else { 4100 if (Set.is_disjoint(Context)) 4101 return false; 4102 4103 if (Set.is_subset(InvalidContext)) 4104 return false; 4105 } 4106 return true; 4107 } 4108 4109 bool Scop::trackAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, 4110 AssumptionSign Sign, BasicBlock *BB) { 4111 if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign)) 4112 return false; 4113 4114 // Do never emit trivial assumptions as they only clutter the output. 4115 if (!PollyRemarksMinimal) { 4116 isl::set Univ; 4117 if (Sign == AS_ASSUMPTION) 4118 Univ = isl::set::universe(Set.get_space()); 4119 4120 bool IsTrivial = (Sign == AS_RESTRICTION && Set.is_empty()) || 4121 (Sign == AS_ASSUMPTION && Univ.is_equal(Set)); 4122 4123 if (IsTrivial) 4124 return false; 4125 } 4126 4127 switch (Kind) { 4128 case ALIASING: 4129 AssumptionsAliasing++; 4130 break; 4131 case INBOUNDS: 4132 AssumptionsInbounds++; 4133 break; 4134 case WRAPPING: 4135 AssumptionsWrapping++; 4136 break; 4137 case UNSIGNED: 4138 AssumptionsUnsigned++; 4139 break; 4140 case COMPLEXITY: 4141 AssumptionsComplexity++; 4142 break; 4143 case PROFITABLE: 4144 AssumptionsUnprofitable++; 4145 break; 4146 case ERRORBLOCK: 4147 AssumptionsErrorBlock++; 4148 break; 4149 case INFINITELOOP: 4150 AssumptionsInfiniteLoop++; 4151 break; 4152 case INVARIANTLOAD: 4153 AssumptionsInvariantLoad++; 4154 break; 4155 case DELINEARIZATION: 4156 AssumptionsDelinearization++; 4157 break; 4158 } 4159 4160 auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t"; 4161 std::string Msg = toString(Kind) + Suffix + Set.to_str(); 4162 if (BB) 4163 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, BB) 4164 << Msg); 4165 else 4166 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, 4167 R.getEntry()) 4168 << Msg); 4169 return true; 4170 } 4171 4172 void Scop::addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, 4173 AssumptionSign Sign, BasicBlock *BB) { 4174 // Simplify the assumptions/restrictions first. 4175 Set = Set.gist_params(getContext()); 4176 4177 if (!trackAssumption(Kind, Set, Loc, Sign, BB)) 4178 return; 4179 4180 if (Sign == AS_ASSUMPTION) 4181 AssumedContext = AssumedContext.intersect(Set).coalesce(); 4182 else 4183 InvalidContext = InvalidContext.unite(Set).coalesce(); 4184 } 4185 4186 void Scop::recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, 4187 AssumptionSign Sign, BasicBlock *BB) { 4188 assert((Set.is_params() || BB) && 4189 "Assumptions without a basic block must be parameter sets"); 4190 RecordedAssumptions.push_back({Kind, Sign, Set, Loc, BB}); 4191 } 4192 4193 void Scop::addRecordedAssumptions() { 4194 while (!RecordedAssumptions.empty()) { 4195 Assumption AS = RecordedAssumptions.pop_back_val(); 4196 4197 if (!AS.BB) { 4198 addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign, nullptr /* BasicBlock */); 4199 continue; 4200 } 4201 4202 // If the domain was deleted the assumptions are void. 4203 isl_set *Dom = getDomainConditions(AS.BB).release(); 4204 if (!Dom) 4205 continue; 4206 4207 // If a basic block was given use its domain to simplify the assumption. 4208 // In case of restrictions we know they only have to hold on the domain, 4209 // thus we can intersect them with the domain of the block. However, for 4210 // assumptions the domain has to imply them, thus: 4211 // _ _____ 4212 // Dom => S <==> A v B <==> A - B 4213 // 4214 // To avoid the complement we will register A - B as a restriction not an 4215 // assumption. 4216 isl_set *S = AS.Set.copy(); 4217 if (AS.Sign == AS_RESTRICTION) 4218 S = isl_set_params(isl_set_intersect(S, Dom)); 4219 else /* (AS.Sign == AS_ASSUMPTION) */ 4220 S = isl_set_params(isl_set_subtract(Dom, S)); 4221 4222 addAssumption(AS.Kind, isl::manage(S), AS.Loc, AS_RESTRICTION, AS.BB); 4223 } 4224 } 4225 4226 void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) { 4227 LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n"); 4228 addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB); 4229 } 4230 4231 isl::set Scop::getInvalidContext() const { return InvalidContext; } 4232 4233 void Scop::printContext(raw_ostream &OS) const { 4234 OS << "Context:\n"; 4235 OS.indent(4) << Context << "\n"; 4236 4237 OS.indent(4) << "Assumed Context:\n"; 4238 OS.indent(4) << AssumedContext << "\n"; 4239 4240 OS.indent(4) << "Invalid Context:\n"; 4241 OS.indent(4) << InvalidContext << "\n"; 4242 4243 unsigned Dim = 0; 4244 for (const SCEV *Parameter : Parameters) 4245 OS.indent(4) << "p" << Dim++ << ": " << *Parameter << "\n"; 4246 } 4247 4248 void Scop::printAliasAssumptions(raw_ostream &OS) const { 4249 int noOfGroups = 0; 4250 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 4251 if (Pair.second.size() == 0) 4252 noOfGroups += 1; 4253 else 4254 noOfGroups += Pair.second.size(); 4255 } 4256 4257 OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n"; 4258 if (MinMaxAliasGroups.empty()) { 4259 OS.indent(8) << "n/a\n"; 4260 return; 4261 } 4262 4263 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 4264 4265 // If the group has no read only accesses print the write accesses. 4266 if (Pair.second.empty()) { 4267 OS.indent(8) << "[["; 4268 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 4269 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 4270 << ">"; 4271 } 4272 OS << " ]]\n"; 4273 } 4274 4275 for (const MinMaxAccessTy &MMAReadOnly : Pair.second) { 4276 OS.indent(8) << "[["; 4277 OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">"; 4278 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 4279 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 4280 << ">"; 4281 } 4282 OS << " ]]\n"; 4283 } 4284 } 4285 } 4286 4287 void Scop::printStatements(raw_ostream &OS, bool PrintInstructions) const { 4288 OS << "Statements {\n"; 4289 4290 for (const ScopStmt &Stmt : *this) { 4291 OS.indent(4); 4292 Stmt.print(OS, PrintInstructions); 4293 } 4294 4295 OS.indent(4) << "}\n"; 4296 } 4297 4298 void Scop::printArrayInfo(raw_ostream &OS) const { 4299 OS << "Arrays {\n"; 4300 4301 for (auto &Array : arrays()) 4302 Array->print(OS); 4303 4304 OS.indent(4) << "}\n"; 4305 4306 OS.indent(4) << "Arrays (Bounds as pw_affs) {\n"; 4307 4308 for (auto &Array : arrays()) 4309 Array->print(OS, /* SizeAsPwAff */ true); 4310 4311 OS.indent(4) << "}\n"; 4312 } 4313 4314 void Scop::print(raw_ostream &OS, bool PrintInstructions) const { 4315 OS.indent(4) << "Function: " << getFunction().getName() << "\n"; 4316 OS.indent(4) << "Region: " << getNameStr() << "\n"; 4317 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; 4318 OS.indent(4) << "Invariant Accesses: {\n"; 4319 for (const auto &IAClass : InvariantEquivClasses) { 4320 const auto &MAs = IAClass.InvariantAccesses; 4321 if (MAs.empty()) { 4322 OS.indent(12) << "Class Pointer: " << *IAClass.IdentifyingPointer << "\n"; 4323 } else { 4324 MAs.front()->print(OS); 4325 OS.indent(12) << "Execution Context: " << IAClass.ExecutionContext 4326 << "\n"; 4327 } 4328 } 4329 OS.indent(4) << "}\n"; 4330 printContext(OS.indent(4)); 4331 printArrayInfo(OS.indent(4)); 4332 printAliasAssumptions(OS); 4333 printStatements(OS.indent(4), PrintInstructions); 4334 } 4335 4336 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 4337 LLVM_DUMP_METHOD void Scop::dump() const { print(dbgs(), true); } 4338 #endif 4339 4340 isl::ctx Scop::getIslCtx() const { return IslCtx.get(); } 4341 4342 __isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB, 4343 bool NonNegative) { 4344 // First try to use the SCEVAffinator to generate a piecewise defined 4345 // affine function from @p E in the context of @p BB. If that tasks becomes to 4346 // complex the affinator might return a nullptr. In such a case we invalidate 4347 // the SCoP and return a dummy value. This way we do not need to add error 4348 // handling code to all users of this function. 4349 auto PWAC = Affinator.getPwAff(E, BB); 4350 if (PWAC.first) { 4351 // TODO: We could use a heuristic and either use: 4352 // SCEVAffinator::takeNonNegativeAssumption 4353 // or 4354 // SCEVAffinator::interpretAsUnsigned 4355 // to deal with unsigned or "NonNegative" SCEVs. 4356 if (NonNegative) 4357 Affinator.takeNonNegativeAssumption(PWAC); 4358 return PWAC; 4359 } 4360 4361 auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc(); 4362 invalidate(COMPLEXITY, DL, BB); 4363 return Affinator.getPwAff(SE->getZero(E->getType()), BB); 4364 } 4365 4366 isl::union_set Scop::getDomains() const { 4367 isl_space *EmptySpace = isl_space_params_alloc(getIslCtx().get(), 0); 4368 isl_union_set *Domain = isl_union_set_empty(EmptySpace); 4369 4370 for (const ScopStmt &Stmt : *this) 4371 Domain = isl_union_set_add_set(Domain, Stmt.getDomain().release()); 4372 4373 return isl::manage(Domain); 4374 } 4375 4376 isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB) { 4377 PWACtx PWAC = getPwAff(E, BB); 4378 return PWAC.first; 4379 } 4380 4381 isl::union_map 4382 Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) { 4383 isl::union_map Accesses = isl::union_map::empty(getParamSpace()); 4384 4385 for (ScopStmt &Stmt : *this) { 4386 for (MemoryAccess *MA : Stmt) { 4387 if (!Predicate(*MA)) 4388 continue; 4389 4390 isl::set Domain = Stmt.getDomain(); 4391 isl::map AccessDomain = MA->getAccessRelation(); 4392 AccessDomain = AccessDomain.intersect_domain(Domain); 4393 Accesses = Accesses.add_map(AccessDomain); 4394 } 4395 } 4396 4397 return Accesses.coalesce(); 4398 } 4399 4400 isl::union_map Scop::getMustWrites() { 4401 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); }); 4402 } 4403 4404 isl::union_map Scop::getMayWrites() { 4405 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); }); 4406 } 4407 4408 isl::union_map Scop::getWrites() { 4409 return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); }); 4410 } 4411 4412 isl::union_map Scop::getReads() { 4413 return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); }); 4414 } 4415 4416 isl::union_map Scop::getAccesses() { 4417 return getAccessesOfType([](MemoryAccess &MA) { return true; }); 4418 } 4419 4420 isl::union_map Scop::getAccesses(ScopArrayInfo *Array) { 4421 return getAccessesOfType( 4422 [Array](MemoryAccess &MA) { return MA.getScopArrayInfo() == Array; }); 4423 } 4424 4425 // Check whether @p Node is an extension node. 4426 // 4427 // @return true if @p Node is an extension node. 4428 isl_bool isNotExtNode(__isl_keep isl_schedule_node *Node, void *User) { 4429 if (isl_schedule_node_get_type(Node) == isl_schedule_node_extension) 4430 return isl_bool_error; 4431 else 4432 return isl_bool_true; 4433 } 4434 4435 bool Scop::containsExtensionNode(isl::schedule Schedule) { 4436 return isl_schedule_foreach_schedule_node_top_down( 4437 Schedule.get(), isNotExtNode, nullptr) == isl_stat_error; 4438 } 4439 4440 isl::union_map Scop::getSchedule() const { 4441 auto Tree = getScheduleTree(); 4442 if (containsExtensionNode(Tree)) 4443 return nullptr; 4444 4445 return Tree.get_map(); 4446 } 4447 4448 isl::schedule Scop::getScheduleTree() const { 4449 return Schedule.intersect_domain(getDomains()); 4450 } 4451 4452 void Scop::setSchedule(isl::union_map NewSchedule) { 4453 auto S = isl::schedule::from_domain(getDomains()); 4454 Schedule = S.insert_partial_schedule( 4455 isl::multi_union_pw_aff::from_union_map(NewSchedule)); 4456 ScheduleModified = true; 4457 } 4458 4459 void Scop::setScheduleTree(isl::schedule NewSchedule) { 4460 Schedule = NewSchedule; 4461 ScheduleModified = true; 4462 } 4463 4464 bool Scop::restrictDomains(isl::union_set Domain) { 4465 bool Changed = false; 4466 for (ScopStmt &Stmt : *this) { 4467 isl::union_set StmtDomain = isl::union_set(Stmt.getDomain()); 4468 isl::union_set NewStmtDomain = StmtDomain.intersect(Domain); 4469 4470 if (StmtDomain.is_subset(NewStmtDomain)) 4471 continue; 4472 4473 Changed = true; 4474 4475 NewStmtDomain = NewStmtDomain.coalesce(); 4476 4477 if (NewStmtDomain.is_empty()) 4478 Stmt.restrictDomain(isl::set::empty(Stmt.getDomainSpace())); 4479 else 4480 Stmt.restrictDomain(isl::set(NewStmtDomain)); 4481 } 4482 return Changed; 4483 } 4484 4485 ScalarEvolution *Scop::getSE() const { return SE; } 4486 4487 // Create an isl_multi_union_aff that defines an identity mapping from the 4488 // elements of USet to their N-th dimension. 4489 // 4490 // # Example: 4491 // 4492 // Domain: { A[i,j]; B[i,j,k] } 4493 // N: 1 4494 // 4495 // Resulting Mapping: { {A[i,j] -> [(j)]; B[i,j,k] -> [(j)] } 4496 // 4497 // @param USet A union set describing the elements for which to generate a 4498 // mapping. 4499 // @param N The dimension to map to. 4500 // @returns A mapping from USet to its N-th dimension. 4501 static isl::multi_union_pw_aff mapToDimension(isl::union_set USet, int N) { 4502 assert(N >= 0); 4503 assert(USet); 4504 assert(!USet.is_empty()); 4505 4506 auto Result = isl::union_pw_multi_aff::empty(USet.get_space()); 4507 4508 for (isl::set S : USet.get_set_list()) { 4509 int Dim = S.dim(isl::dim::set); 4510 auto PMA = isl::pw_multi_aff::project_out_map(S.get_space(), isl::dim::set, 4511 N, Dim - N); 4512 if (N > 1) 4513 PMA = PMA.drop_dims(isl::dim::out, 0, N - 1); 4514 4515 Result = Result.add_pw_multi_aff(PMA); 4516 } 4517 4518 return isl::multi_union_pw_aff(isl::union_pw_multi_aff(Result)); 4519 } 4520 4521 void Scop::addScopStmt(BasicBlock *BB, StringRef Name, Loop *SurroundingLoop, 4522 std::vector<Instruction *> Instructions) { 4523 assert(BB && "Unexpected nullptr!"); 4524 Stmts.emplace_back(*this, *BB, Name, SurroundingLoop, Instructions); 4525 auto *Stmt = &Stmts.back(); 4526 StmtMap[BB].push_back(Stmt); 4527 for (Instruction *Inst : Instructions) { 4528 assert(!InstStmtMap.count(Inst) && 4529 "Unexpected statement corresponding to the instruction."); 4530 InstStmtMap[Inst] = Stmt; 4531 } 4532 } 4533 4534 void Scop::addScopStmt(Region *R, StringRef Name, Loop *SurroundingLoop, 4535 std::vector<Instruction *> Instructions) { 4536 assert(R && "Unexpected nullptr!"); 4537 Stmts.emplace_back(*this, *R, Name, SurroundingLoop, Instructions); 4538 auto *Stmt = &Stmts.back(); 4539 4540 for (Instruction *Inst : Instructions) { 4541 assert(!InstStmtMap.count(Inst) && 4542 "Unexpected statement corresponding to the instruction."); 4543 InstStmtMap[Inst] = Stmt; 4544 } 4545 4546 for (BasicBlock *BB : R->blocks()) { 4547 StmtMap[BB].push_back(Stmt); 4548 if (BB == R->getEntry()) 4549 continue; 4550 for (Instruction &Inst : *BB) { 4551 assert(!InstStmtMap.count(&Inst) && 4552 "Unexpected statement corresponding to the instruction."); 4553 InstStmtMap[&Inst] = Stmt; 4554 } 4555 } 4556 } 4557 4558 ScopStmt *Scop::addScopStmt(isl::map SourceRel, isl::map TargetRel, 4559 isl::set Domain) { 4560 #ifndef NDEBUG 4561 isl::set SourceDomain = SourceRel.domain(); 4562 isl::set TargetDomain = TargetRel.domain(); 4563 assert(Domain.is_subset(TargetDomain) && 4564 "Target access not defined for complete statement domain"); 4565 assert(Domain.is_subset(SourceDomain) && 4566 "Source access not defined for complete statement domain"); 4567 #endif 4568 Stmts.emplace_back(*this, SourceRel, TargetRel, Domain); 4569 CopyStmtsNum++; 4570 return &(Stmts.back()); 4571 } 4572 4573 void Scop::buildSchedule(LoopInfo &LI) { 4574 Loop *L = getLoopSurroundingScop(*this, LI); 4575 LoopStackTy LoopStack({LoopStackElementTy(L, nullptr, 0)}); 4576 buildSchedule(getRegion().getNode(), LoopStack, LI); 4577 assert(LoopStack.size() == 1 && LoopStack.back().L == L); 4578 Schedule = LoopStack[0].Schedule; 4579 } 4580 4581 /// To generate a schedule for the elements in a Region we traverse the Region 4582 /// in reverse-post-order and add the contained RegionNodes in traversal order 4583 /// to the schedule of the loop that is currently at the top of the LoopStack. 4584 /// For loop-free codes, this results in a correct sequential ordering. 4585 /// 4586 /// Example: 4587 /// bb1(0) 4588 /// / \. 4589 /// bb2(1) bb3(2) 4590 /// \ / \. 4591 /// bb4(3) bb5(4) 4592 /// \ / 4593 /// bb6(5) 4594 /// 4595 /// Including loops requires additional processing. Whenever a loop header is 4596 /// encountered, the corresponding loop is added to the @p LoopStack. Starting 4597 /// from an empty schedule, we first process all RegionNodes that are within 4598 /// this loop and complete the sequential schedule at this loop-level before 4599 /// processing about any other nodes. To implement this 4600 /// loop-nodes-first-processing, the reverse post-order traversal is 4601 /// insufficient. Hence, we additionally check if the traversal yields 4602 /// sub-regions or blocks that are outside the last loop on the @p LoopStack. 4603 /// These region-nodes are then queue and only traverse after the all nodes 4604 /// within the current loop have been processed. 4605 void Scop::buildSchedule(Region *R, LoopStackTy &LoopStack, LoopInfo &LI) { 4606 Loop *OuterScopLoop = getLoopSurroundingScop(*this, LI); 4607 4608 ReversePostOrderTraversal<Region *> RTraversal(R); 4609 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end()); 4610 std::deque<RegionNode *> DelayList; 4611 bool LastRNWaiting = false; 4612 4613 // Iterate over the region @p R in reverse post-order but queue 4614 // sub-regions/blocks iff they are not part of the last encountered but not 4615 // completely traversed loop. The variable LastRNWaiting is a flag to indicate 4616 // that we queued the last sub-region/block from the reverse post-order 4617 // iterator. If it is set we have to explore the next sub-region/block from 4618 // the iterator (if any) to guarantee progress. If it is not set we first try 4619 // the next queued sub-region/blocks. 4620 while (!WorkList.empty() || !DelayList.empty()) { 4621 RegionNode *RN; 4622 4623 if ((LastRNWaiting && !WorkList.empty()) || DelayList.empty()) { 4624 RN = WorkList.front(); 4625 WorkList.pop_front(); 4626 LastRNWaiting = false; 4627 } else { 4628 RN = DelayList.front(); 4629 DelayList.pop_front(); 4630 } 4631 4632 Loop *L = getRegionNodeLoop(RN, LI); 4633 if (!contains(L)) 4634 L = OuterScopLoop; 4635 4636 Loop *LastLoop = LoopStack.back().L; 4637 if (LastLoop != L) { 4638 if (LastLoop && !LastLoop->contains(L)) { 4639 LastRNWaiting = true; 4640 DelayList.push_back(RN); 4641 continue; 4642 } 4643 LoopStack.push_back({L, nullptr, 0}); 4644 } 4645 buildSchedule(RN, LoopStack, LI); 4646 } 4647 } 4648 4649 void Scop::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack, LoopInfo &LI) { 4650 if (RN->isSubRegion()) { 4651 auto *LocalRegion = RN->getNodeAs<Region>(); 4652 if (!isNonAffineSubRegion(LocalRegion)) { 4653 buildSchedule(LocalRegion, LoopStack, LI); 4654 return; 4655 } 4656 } 4657 4658 assert(LoopStack.rbegin() != LoopStack.rend()); 4659 auto LoopData = LoopStack.rbegin(); 4660 LoopData->NumBlocksProcessed += getNumBlocksInRegionNode(RN); 4661 4662 for (auto *Stmt : getStmtListFor(RN)) { 4663 isl::union_set UDomain{Stmt->getDomain()}; 4664 auto StmtSchedule = isl::schedule::from_domain(UDomain); 4665 LoopData->Schedule = combineInSequence(LoopData->Schedule, StmtSchedule); 4666 } 4667 4668 // Check if we just processed the last node in this loop. If we did, finalize 4669 // the loop by: 4670 // 4671 // - adding new schedule dimensions 4672 // - folding the resulting schedule into the parent loop schedule 4673 // - dropping the loop schedule from the LoopStack. 4674 // 4675 // Then continue to check surrounding loops, which might also have been 4676 // completed by this node. 4677 size_t Dimension = LoopStack.size(); 4678 while (LoopData->L && 4679 LoopData->NumBlocksProcessed == getNumBlocksInLoop(LoopData->L)) { 4680 isl::schedule Schedule = LoopData->Schedule; 4681 auto NumBlocksProcessed = LoopData->NumBlocksProcessed; 4682 4683 assert(std::next(LoopData) != LoopStack.rend()); 4684 ++LoopData; 4685 --Dimension; 4686 4687 if (Schedule) { 4688 isl::union_set Domain = Schedule.get_domain(); 4689 isl::multi_union_pw_aff MUPA = mapToDimension(Domain, Dimension); 4690 Schedule = Schedule.insert_partial_schedule(MUPA); 4691 LoopData->Schedule = combineInSequence(LoopData->Schedule, Schedule); 4692 } 4693 4694 LoopData->NumBlocksProcessed += NumBlocksProcessed; 4695 } 4696 // Now pop all loops processed up there from the LoopStack 4697 LoopStack.erase(LoopStack.begin() + Dimension, LoopStack.end()); 4698 } 4699 4700 ArrayRef<ScopStmt *> Scop::getStmtListFor(BasicBlock *BB) const { 4701 auto StmtMapIt = StmtMap.find(BB); 4702 if (StmtMapIt == StmtMap.end()) 4703 return {}; 4704 return StmtMapIt->second; 4705 } 4706 4707 ScopStmt *Scop::getIncomingStmtFor(const Use &U) const { 4708 auto *PHI = cast<PHINode>(U.getUser()); 4709 BasicBlock *IncomingBB = PHI->getIncomingBlock(U); 4710 4711 // If the value is a non-synthesizable from the incoming block, use the 4712 // statement that contains it as user statement. 4713 if (auto *IncomingInst = dyn_cast<Instruction>(U.get())) { 4714 if (IncomingInst->getParent() == IncomingBB) { 4715 if (ScopStmt *IncomingStmt = getStmtFor(IncomingInst)) 4716 return IncomingStmt; 4717 } 4718 } 4719 4720 // Otherwise, use the epilogue/last statement. 4721 return getLastStmtFor(IncomingBB); 4722 } 4723 4724 ScopStmt *Scop::getLastStmtFor(BasicBlock *BB) const { 4725 ArrayRef<ScopStmt *> StmtList = getStmtListFor(BB); 4726 if (!StmtList.empty()) 4727 return StmtList.back(); 4728 return nullptr; 4729 } 4730 4731 ArrayRef<ScopStmt *> Scop::getStmtListFor(RegionNode *RN) const { 4732 if (RN->isSubRegion()) 4733 return getStmtListFor(RN->getNodeAs<Region>()); 4734 return getStmtListFor(RN->getNodeAs<BasicBlock>()); 4735 } 4736 4737 ArrayRef<ScopStmt *> Scop::getStmtListFor(Region *R) const { 4738 return getStmtListFor(R->getEntry()); 4739 } 4740 4741 int Scop::getRelativeLoopDepth(const Loop *L) const { 4742 if (!L || !R.contains(L)) 4743 return -1; 4744 // outermostLoopInRegion always returns nullptr for top level regions 4745 if (R.isTopLevelRegion()) { 4746 // LoopInfo's depths start at 1, we start at 0 4747 return L->getLoopDepth() - 1; 4748 } else { 4749 Loop *OuterLoop = R.outermostLoopInRegion(const_cast<Loop *>(L)); 4750 assert(OuterLoop); 4751 return L->getLoopDepth() - OuterLoop->getLoopDepth(); 4752 } 4753 } 4754 4755 ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) { 4756 for (auto &SAI : arrays()) { 4757 if (SAI->getName() == BaseName) 4758 return SAI; 4759 } 4760 return nullptr; 4761 } 4762 4763 void Scop::addAccessData(MemoryAccess *Access) { 4764 const ScopArrayInfo *SAI = Access->getOriginalScopArrayInfo(); 4765 assert(SAI && "can only use after access relations have been constructed"); 4766 4767 if (Access->isOriginalValueKind() && Access->isRead()) 4768 ValueUseAccs[SAI].push_back(Access); 4769 else if (Access->isOriginalAnyPHIKind() && Access->isWrite()) 4770 PHIIncomingAccs[SAI].push_back(Access); 4771 } 4772 4773 void Scop::removeAccessData(MemoryAccess *Access) { 4774 if (Access->isOriginalValueKind() && Access->isWrite()) { 4775 ValueDefAccs.erase(Access->getAccessValue()); 4776 } else if (Access->isOriginalValueKind() && Access->isRead()) { 4777 auto &Uses = ValueUseAccs[Access->getScopArrayInfo()]; 4778 auto NewEnd = std::remove(Uses.begin(), Uses.end(), Access); 4779 Uses.erase(NewEnd, Uses.end()); 4780 } else if (Access->isOriginalPHIKind() && Access->isRead()) { 4781 PHINode *PHI = cast<PHINode>(Access->getAccessInstruction()); 4782 PHIReadAccs.erase(PHI); 4783 } else if (Access->isOriginalAnyPHIKind() && Access->isWrite()) { 4784 auto &Incomings = PHIIncomingAccs[Access->getScopArrayInfo()]; 4785 auto NewEnd = std::remove(Incomings.begin(), Incomings.end(), Access); 4786 Incomings.erase(NewEnd, Incomings.end()); 4787 } 4788 } 4789 4790 MemoryAccess *Scop::getValueDef(const ScopArrayInfo *SAI) const { 4791 assert(SAI->isValueKind()); 4792 4793 Instruction *Val = dyn_cast<Instruction>(SAI->getBasePtr()); 4794 if (!Val) 4795 return nullptr; 4796 4797 return ValueDefAccs.lookup(Val); 4798 } 4799 4800 ArrayRef<MemoryAccess *> Scop::getValueUses(const ScopArrayInfo *SAI) const { 4801 assert(SAI->isValueKind()); 4802 auto It = ValueUseAccs.find(SAI); 4803 if (It == ValueUseAccs.end()) 4804 return {}; 4805 return It->second; 4806 } 4807 4808 MemoryAccess *Scop::getPHIRead(const ScopArrayInfo *SAI) const { 4809 assert(SAI->isPHIKind() || SAI->isExitPHIKind()); 4810 4811 if (SAI->isExitPHIKind()) 4812 return nullptr; 4813 4814 PHINode *PHI = cast<PHINode>(SAI->getBasePtr()); 4815 return PHIReadAccs.lookup(PHI); 4816 } 4817 4818 ArrayRef<MemoryAccess *> Scop::getPHIIncomings(const ScopArrayInfo *SAI) const { 4819 assert(SAI->isPHIKind() || SAI->isExitPHIKind()); 4820 auto It = PHIIncomingAccs.find(SAI); 4821 if (It == PHIIncomingAccs.end()) 4822 return {}; 4823 return It->second; 4824 } 4825 4826 bool Scop::isEscaping(Instruction *Inst) { 4827 assert(contains(Inst) && "The concept of escaping makes only sense for " 4828 "values defined inside the SCoP"); 4829 4830 for (Use &Use : Inst->uses()) { 4831 BasicBlock *UserBB = getUseBlock(Use); 4832 if (!contains(UserBB)) 4833 return true; 4834 4835 // When the SCoP region exit needs to be simplified, PHIs in the region exit 4836 // move to a new basic block such that its incoming blocks are not in the 4837 // SCoP anymore. 4838 if (hasSingleExitEdge() && isa<PHINode>(Use.getUser()) && 4839 isExit(cast<PHINode>(Use.getUser())->getParent())) 4840 return true; 4841 } 4842 return false; 4843 } 4844 4845 Scop::ScopStatistics Scop::getStatistics() const { 4846 ScopStatistics Result; 4847 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 4848 auto LoopStat = ScopDetection::countBeneficialLoops(&R, *SE, *getLI(), 0); 4849 4850 int NumTotalLoops = LoopStat.NumLoops; 4851 Result.NumBoxedLoops = getBoxedLoops().size(); 4852 Result.NumAffineLoops = NumTotalLoops - Result.NumBoxedLoops; 4853 4854 for (const ScopStmt &Stmt : *this) { 4855 isl::set Domain = Stmt.getDomain().intersect_params(getContext()); 4856 bool IsInLoop = Stmt.getNumIterators() >= 1; 4857 for (MemoryAccess *MA : Stmt) { 4858 if (!MA->isWrite()) 4859 continue; 4860 4861 if (MA->isLatestValueKind()) { 4862 Result.NumValueWrites += 1; 4863 if (IsInLoop) 4864 Result.NumValueWritesInLoops += 1; 4865 } 4866 4867 if (MA->isLatestAnyPHIKind()) { 4868 Result.NumPHIWrites += 1; 4869 if (IsInLoop) 4870 Result.NumPHIWritesInLoops += 1; 4871 } 4872 4873 isl::set AccSet = 4874 MA->getAccessRelation().intersect_domain(Domain).range(); 4875 if (AccSet.is_singleton()) { 4876 Result.NumSingletonWrites += 1; 4877 if (IsInLoop) 4878 Result.NumSingletonWritesInLoops += 1; 4879 } 4880 } 4881 } 4882 #endif 4883 return Result; 4884 } 4885 4886 raw_ostream &polly::operator<<(raw_ostream &OS, const Scop &scop) { 4887 scop.print(OS, PollyPrintInstructions); 4888 return OS; 4889 } 4890 4891 //===----------------------------------------------------------------------===// 4892 void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const { 4893 AU.addRequired<LoopInfoWrapperPass>(); 4894 AU.addRequired<RegionInfoPass>(); 4895 AU.addRequired<DominatorTreeWrapperPass>(); 4896 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 4897 AU.addRequiredTransitive<ScopDetectionWrapperPass>(); 4898 AU.addRequired<AAResultsWrapperPass>(); 4899 AU.addRequired<AssumptionCacheTracker>(); 4900 AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); 4901 AU.setPreservesAll(); 4902 } 4903 4904 void updateLoopCountStatistic(ScopDetection::LoopStats Stats, 4905 Scop::ScopStatistics ScopStats) { 4906 assert(Stats.NumLoops == ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops); 4907 4908 NumScops++; 4909 NumLoopsInScop += Stats.NumLoops; 4910 MaxNumLoopsInScop = 4911 std::max(MaxNumLoopsInScop.getValue(), (unsigned)Stats.NumLoops); 4912 4913 if (Stats.MaxDepth == 0) 4914 NumScopsDepthZero++; 4915 else if (Stats.MaxDepth == 1) 4916 NumScopsDepthOne++; 4917 else if (Stats.MaxDepth == 2) 4918 NumScopsDepthTwo++; 4919 else if (Stats.MaxDepth == 3) 4920 NumScopsDepthThree++; 4921 else if (Stats.MaxDepth == 4) 4922 NumScopsDepthFour++; 4923 else if (Stats.MaxDepth == 5) 4924 NumScopsDepthFive++; 4925 else 4926 NumScopsDepthLarger++; 4927 4928 NumAffineLoops += ScopStats.NumAffineLoops; 4929 NumBoxedLoops += ScopStats.NumBoxedLoops; 4930 4931 NumValueWrites += ScopStats.NumValueWrites; 4932 NumValueWritesInLoops += ScopStats.NumValueWritesInLoops; 4933 NumPHIWrites += ScopStats.NumPHIWrites; 4934 NumPHIWritesInLoops += ScopStats.NumPHIWritesInLoops; 4935 NumSingletonWrites += ScopStats.NumSingletonWrites; 4936 NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops; 4937 } 4938 4939 bool ScopInfoRegionPass::runOnRegion(Region *R, RGPassManager &RGM) { 4940 auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD(); 4941 4942 if (!SD.isMaxRegionInScop(*R)) 4943 return false; 4944 4945 Function *F = R->getEntry()->getParent(); 4946 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 4947 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 4948 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); 4949 auto const &DL = F->getParent()->getDataLayout(); 4950 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 4951 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F); 4952 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); 4953 4954 ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE); 4955 S = SB.getScop(); // take ownership of scop object 4956 4957 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 4958 if (S) { 4959 ScopDetection::LoopStats Stats = 4960 ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0); 4961 updateLoopCountStatistic(Stats, S->getStatistics()); 4962 } 4963 #endif 4964 4965 return false; 4966 } 4967 4968 void ScopInfoRegionPass::print(raw_ostream &OS, const Module *) const { 4969 if (S) 4970 S->print(OS, PollyPrintInstructions); 4971 else 4972 OS << "Invalid Scop!\n"; 4973 } 4974 4975 char ScopInfoRegionPass::ID = 0; 4976 4977 Pass *polly::createScopInfoRegionPassPass() { return new ScopInfoRegionPass(); } 4978 4979 INITIALIZE_PASS_BEGIN(ScopInfoRegionPass, "polly-scops", 4980 "Polly - Create polyhedral description of Scops", false, 4981 false); 4982 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); 4983 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); 4984 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 4985 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 4986 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 4987 INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); 4988 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 4989 INITIALIZE_PASS_END(ScopInfoRegionPass, "polly-scops", 4990 "Polly - Create polyhedral description of Scops", false, 4991 false) 4992 4993 //===----------------------------------------------------------------------===// 4994 ScopInfo::ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE, 4995 LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT, 4996 AssumptionCache &AC, OptimizationRemarkEmitter &ORE) 4997 : DL(DL), SD(SD), SE(SE), LI(LI), AA(AA), DT(DT), AC(AC), ORE(ORE) { 4998 recompute(); 4999 } 5000 5001 void ScopInfo::recompute() { 5002 RegionToScopMap.clear(); 5003 /// Create polyhedral description of scops for all the valid regions of a 5004 /// function. 5005 for (auto &It : SD) { 5006 Region *R = const_cast<Region *>(It); 5007 if (!SD.isMaxRegionInScop(*R)) 5008 continue; 5009 5010 ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE); 5011 std::unique_ptr<Scop> S = SB.getScop(); 5012 if (!S) 5013 continue; 5014 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 5015 ScopDetection::LoopStats Stats = 5016 ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0); 5017 updateLoopCountStatistic(Stats, S->getStatistics()); 5018 #endif 5019 bool Inserted = RegionToScopMap.insert({R, std::move(S)}).second; 5020 assert(Inserted && "Building Scop for the same region twice!"); 5021 (void)Inserted; 5022 } 5023 } 5024 5025 bool ScopInfo::invalidate(Function &F, const PreservedAnalyses &PA, 5026 FunctionAnalysisManager::Invalidator &Inv) { 5027 // Check whether the analysis, all analyses on functions have been preserved 5028 // or anything we're holding references to is being invalidated 5029 auto PAC = PA.getChecker<ScopInfoAnalysis>(); 5030 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) || 5031 Inv.invalidate<ScopAnalysis>(F, PA) || 5032 Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) || 5033 Inv.invalidate<LoopAnalysis>(F, PA) || 5034 Inv.invalidate<AAManager>(F, PA) || 5035 Inv.invalidate<DominatorTreeAnalysis>(F, PA) || 5036 Inv.invalidate<AssumptionAnalysis>(F, PA); 5037 } 5038 5039 AnalysisKey ScopInfoAnalysis::Key; 5040 5041 ScopInfoAnalysis::Result ScopInfoAnalysis::run(Function &F, 5042 FunctionAnalysisManager &FAM) { 5043 auto &SD = FAM.getResult<ScopAnalysis>(F); 5044 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F); 5045 auto &LI = FAM.getResult<LoopAnalysis>(F); 5046 auto &AA = FAM.getResult<AAManager>(F); 5047 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); 5048 auto &AC = FAM.getResult<AssumptionAnalysis>(F); 5049 auto &DL = F.getParent()->getDataLayout(); 5050 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F); 5051 return {DL, SD, SE, LI, AA, DT, AC, ORE}; 5052 } 5053 5054 PreservedAnalyses ScopInfoPrinterPass::run(Function &F, 5055 FunctionAnalysisManager &FAM) { 5056 auto &SI = FAM.getResult<ScopInfoAnalysis>(F); 5057 // Since the legacy PM processes Scops in bottom up, we print them in reverse 5058 // order here to keep the output persistent 5059 for (auto &It : reverse(SI)) { 5060 if (It.second) 5061 It.second->print(Stream, PollyPrintInstructions); 5062 else 5063 Stream << "Invalid Scop!\n"; 5064 } 5065 return PreservedAnalyses::all(); 5066 } 5067 5068 void ScopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 5069 AU.addRequired<LoopInfoWrapperPass>(); 5070 AU.addRequired<RegionInfoPass>(); 5071 AU.addRequired<DominatorTreeWrapperPass>(); 5072 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 5073 AU.addRequiredTransitive<ScopDetectionWrapperPass>(); 5074 AU.addRequired<AAResultsWrapperPass>(); 5075 AU.addRequired<AssumptionCacheTracker>(); 5076 AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); 5077 AU.setPreservesAll(); 5078 } 5079 5080 bool ScopInfoWrapperPass::runOnFunction(Function &F) { 5081 auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD(); 5082 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 5083 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 5084 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); 5085 auto const &DL = F.getParent()->getDataLayout(); 5086 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 5087 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 5088 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); 5089 5090 Result.reset(new ScopInfo{DL, SD, SE, LI, AA, DT, AC, ORE}); 5091 return false; 5092 } 5093 5094 void ScopInfoWrapperPass::print(raw_ostream &OS, const Module *) const { 5095 for (auto &It : *Result) { 5096 if (It.second) 5097 It.second->print(OS, PollyPrintInstructions); 5098 else 5099 OS << "Invalid Scop!\n"; 5100 } 5101 } 5102 5103 char ScopInfoWrapperPass::ID = 0; 5104 5105 Pass *polly::createScopInfoWrapperPassPass() { 5106 return new ScopInfoWrapperPass(); 5107 } 5108 5109 INITIALIZE_PASS_BEGIN( 5110 ScopInfoWrapperPass, "polly-function-scops", 5111 "Polly - Create polyhedral description of all Scops of a function", false, 5112 false); 5113 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); 5114 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); 5115 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 5116 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 5117 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 5118 INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); 5119 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 5120 INITIALIZE_PASS_END( 5121 ScopInfoWrapperPass, "polly-function-scops", 5122 "Polly - Create polyhedral description of all Scops of a function", false, 5123 false) 5124