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/Sequence.h" 34 #include "llvm/ADT/SmallPtrSet.h" 35 #include "llvm/ADT/SmallSet.h" 36 #include "llvm/ADT/Statistic.h" 37 #include "llvm/Analysis/AliasAnalysis.h" 38 #include "llvm/Analysis/AssumptionCache.h" 39 #include "llvm/Analysis/Loads.h" 40 #include "llvm/Analysis/LoopInfo.h" 41 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 42 #include "llvm/Analysis/RegionInfo.h" 43 #include "llvm/Analysis/RegionIterator.h" 44 #include "llvm/Analysis/ScalarEvolution.h" 45 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 46 #include "llvm/IR/BasicBlock.h" 47 #include "llvm/IR/ConstantRange.h" 48 #include "llvm/IR/DataLayout.h" 49 #include "llvm/IR/DebugLoc.h" 50 #include "llvm/IR/Dominators.h" 51 #include "llvm/IR/Function.h" 52 #include "llvm/IR/InstrTypes.h" 53 #include "llvm/IR/Instruction.h" 54 #include "llvm/IR/Instructions.h" 55 #include "llvm/IR/Module.h" 56 #include "llvm/IR/PassManager.h" 57 #include "llvm/IR/Type.h" 58 #include "llvm/IR/Value.h" 59 #include "llvm/InitializePasses.h" 60 #include "llvm/Support/Compiler.h" 61 #include "llvm/Support/Debug.h" 62 #include "llvm/Support/ErrorHandling.h" 63 #include "llvm/Support/raw_ostream.h" 64 #include "isl/aff.h" 65 #include "isl/local_space.h" 66 #include "isl/map.h" 67 #include "isl/options.h" 68 #include "isl/set.h" 69 #include <cassert> 70 71 using namespace llvm; 72 using namespace polly; 73 74 #define DEBUG_TYPE "polly-scops" 75 76 STATISTIC(AssumptionsAliasing, "Number of aliasing assumptions taken."); 77 STATISTIC(AssumptionsInbounds, "Number of inbounds assumptions taken."); 78 STATISTIC(AssumptionsWrapping, "Number of wrapping assumptions taken."); 79 STATISTIC(AssumptionsUnsigned, "Number of unsigned assumptions taken."); 80 STATISTIC(AssumptionsComplexity, "Number of too complex SCoPs."); 81 STATISTIC(AssumptionsUnprofitable, "Number of unprofitable SCoPs."); 82 STATISTIC(AssumptionsErrorBlock, "Number of error block assumptions taken."); 83 STATISTIC(AssumptionsInfiniteLoop, "Number of bounded loop assumptions taken."); 84 STATISTIC(AssumptionsInvariantLoad, 85 "Number of invariant loads assumptions taken."); 86 STATISTIC(AssumptionsDelinearization, 87 "Number of delinearization assumptions taken."); 88 89 STATISTIC(NumScops, "Number of feasible SCoPs after ScopInfo"); 90 STATISTIC(NumLoopsInScop, "Number of loops in scops"); 91 STATISTIC(NumBoxedLoops, "Number of boxed loops in SCoPs after ScopInfo"); 92 STATISTIC(NumAffineLoops, "Number of affine loops in SCoPs after ScopInfo"); 93 94 STATISTIC(NumScopsDepthZero, "Number of scops with maximal loop depth 0"); 95 STATISTIC(NumScopsDepthOne, "Number of scops with maximal loop depth 1"); 96 STATISTIC(NumScopsDepthTwo, "Number of scops with maximal loop depth 2"); 97 STATISTIC(NumScopsDepthThree, "Number of scops with maximal loop depth 3"); 98 STATISTIC(NumScopsDepthFour, "Number of scops with maximal loop depth 4"); 99 STATISTIC(NumScopsDepthFive, "Number of scops with maximal loop depth 5"); 100 STATISTIC(NumScopsDepthLarger, 101 "Number of scops with maximal loop depth 6 and larger"); 102 STATISTIC(MaxNumLoopsInScop, "Maximal number of loops in scops"); 103 104 STATISTIC(NumValueWrites, "Number of scalar value writes after ScopInfo"); 105 STATISTIC( 106 NumValueWritesInLoops, 107 "Number of scalar value writes nested in affine loops after ScopInfo"); 108 STATISTIC(NumPHIWrites, "Number of scalar phi writes after ScopInfo"); 109 STATISTIC(NumPHIWritesInLoops, 110 "Number of scalar phi writes nested in affine loops after ScopInfo"); 111 STATISTIC(NumSingletonWrites, "Number of singleton writes after ScopInfo"); 112 STATISTIC(NumSingletonWritesInLoops, 113 "Number of singleton writes nested in affine loops after ScopInfo"); 114 115 int const polly::MaxDisjunctsInDomain = 20; 116 117 // The number of disjunct in the context after which we stop to add more 118 // disjuncts. This parameter is there to avoid exponential growth in the 119 // number of disjunct when adding non-convex sets to the context. 120 static int const MaxDisjunctsInContext = 4; 121 122 // Be a bit more generous for the defined behavior context which is used less 123 // often. 124 static int const MaxDisjunktsInDefinedBehaviourContext = 8; 125 126 static cl::opt<bool> PollyRemarksMinimal( 127 "polly-remarks-minimal", 128 cl::desc("Do not emit remarks about assumptions that are known"), 129 cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); 130 131 static cl::opt<bool> 132 IslOnErrorAbort("polly-on-isl-error-abort", 133 cl::desc("Abort if an isl error is encountered"), 134 cl::init(true), cl::cat(PollyCategory)); 135 136 static cl::opt<bool> PollyPreciseInbounds( 137 "polly-precise-inbounds", 138 cl::desc("Take more precise inbounds assumptions (do not scale well)"), 139 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 140 141 static cl::opt<bool> PollyIgnoreParamBounds( 142 "polly-ignore-parameter-bounds", 143 cl::desc( 144 "Do not add parameter bounds and do no gist simplify sets accordingly"), 145 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 146 147 static cl::opt<bool> PollyPreciseFoldAccesses( 148 "polly-precise-fold-accesses", 149 cl::desc("Fold memory accesses to model more possible delinearizations " 150 "(does not scale well)"), 151 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 152 153 bool polly::UseInstructionNames; 154 155 static cl::opt<bool, true> XUseInstructionNames( 156 "polly-use-llvm-names", 157 cl::desc("Use LLVM-IR names when deriving statement names"), 158 cl::location(UseInstructionNames), cl::Hidden, cl::init(false), 159 cl::ZeroOrMore, cl::cat(PollyCategory)); 160 161 static cl::opt<bool> PollyPrintInstructions( 162 "polly-print-instructions", cl::desc("Output instructions per ScopStmt"), 163 cl::Hidden, cl::Optional, cl::init(false), cl::cat(PollyCategory)); 164 165 static cl::list<std::string> IslArgs("polly-isl-arg", 166 cl::value_desc("argument"), 167 cl::desc("Option passed to ISL"), 168 cl::ZeroOrMore, cl::cat(PollyCategory)); 169 170 //===----------------------------------------------------------------------===// 171 172 static isl::set addRangeBoundsToSet(isl::set S, const ConstantRange &Range, 173 int dim, isl::dim type) { 174 isl::val V; 175 isl::ctx Ctx = S.get_ctx(); 176 177 // The upper and lower bound for a parameter value is derived either from 178 // the data type of the parameter or from the - possibly more restrictive - 179 // range metadata. 180 V = valFromAPInt(Ctx.get(), Range.getSignedMin(), true); 181 S = S.lower_bound_val(type, dim, V); 182 V = valFromAPInt(Ctx.get(), Range.getSignedMax(), true); 183 S = S.upper_bound_val(type, dim, V); 184 185 if (Range.isFullSet()) 186 return S; 187 188 if (S.n_basic_set() > MaxDisjunctsInContext) 189 return S; 190 191 // In case of signed wrapping, we can refine the set of valid values by 192 // excluding the part not covered by the wrapping range. 193 if (Range.isSignWrappedSet()) { 194 V = valFromAPInt(Ctx.get(), Range.getLower(), true); 195 isl::set SLB = S.lower_bound_val(type, dim, V); 196 197 V = valFromAPInt(Ctx.get(), Range.getUpper(), true); 198 V = V.sub_ui(1); 199 isl::set SUB = S.upper_bound_val(type, dim, V); 200 S = SLB.unite(SUB); 201 } 202 203 return S; 204 } 205 206 static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) { 207 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr); 208 if (!BasePtrLI) 209 return nullptr; 210 211 if (!S->contains(BasePtrLI)) 212 return nullptr; 213 214 ScalarEvolution &SE = *S->getSE(); 215 216 auto *OriginBaseSCEV = 217 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand())); 218 if (!OriginBaseSCEV) 219 return nullptr; 220 221 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV); 222 if (!OriginBaseSCEVUnknown) 223 return nullptr; 224 225 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(), 226 MemoryKind::Array); 227 } 228 229 ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl::ctx Ctx, 230 ArrayRef<const SCEV *> Sizes, MemoryKind Kind, 231 const DataLayout &DL, Scop *S, 232 const char *BaseName) 233 : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) { 234 std::string BasePtrName = 235 BaseName ? BaseName 236 : getIslCompatibleName("MemRef", BasePtr, S->getNextArrayIdx(), 237 Kind == MemoryKind::PHI ? "__phi" : "", 238 UseInstructionNames); 239 Id = isl::id::alloc(Ctx, BasePtrName, this); 240 241 updateSizes(Sizes); 242 243 if (!BasePtr || Kind != MemoryKind::Array) { 244 BasePtrOriginSAI = nullptr; 245 return; 246 } 247 248 BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr); 249 if (BasePtrOriginSAI) 250 const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this); 251 } 252 253 ScopArrayInfo::~ScopArrayInfo() = default; 254 255 isl::space ScopArrayInfo::getSpace() const { 256 auto Space = isl::space(Id.get_ctx(), 0, getNumberOfDimensions()); 257 Space = Space.set_tuple_id(isl::dim::set, Id); 258 return Space; 259 } 260 261 bool ScopArrayInfo::isReadOnly() { 262 isl::union_set WriteSet = S.getWrites().range(); 263 isl::space Space = getSpace(); 264 WriteSet = WriteSet.extract_set(Space); 265 266 return bool(WriteSet.is_empty()); 267 } 268 269 bool ScopArrayInfo::isCompatibleWith(const ScopArrayInfo *Array) const { 270 if (Array->getElementType() != getElementType()) 271 return false; 272 273 if (Array->getNumberOfDimensions() != getNumberOfDimensions()) 274 return false; 275 276 for (unsigned i = 0; i < getNumberOfDimensions(); i++) 277 if (Array->getDimensionSize(i) != getDimensionSize(i)) 278 return false; 279 280 return true; 281 } 282 283 void ScopArrayInfo::updateElementType(Type *NewElementType) { 284 if (NewElementType == ElementType) 285 return; 286 287 auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType); 288 auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType); 289 290 if (NewElementSize == OldElementSize || NewElementSize == 0) 291 return; 292 293 if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) { 294 ElementType = NewElementType; 295 } else { 296 auto GCD = GreatestCommonDivisor64(NewElementSize, OldElementSize); 297 ElementType = IntegerType::get(ElementType->getContext(), GCD); 298 } 299 } 300 301 /// Make the ScopArrayInfo model a Fortran Array 302 void ScopArrayInfo::applyAndSetFAD(Value *FAD) { 303 assert(FAD && "got invalid Fortran array descriptor"); 304 if (this->FAD) { 305 assert(this->FAD == FAD && 306 "receiving different array descriptors for same array"); 307 return; 308 } 309 310 assert(DimensionSizesPw.size() > 0 && DimensionSizesPw[0].is_null()); 311 assert(!this->FAD); 312 this->FAD = FAD; 313 314 isl::space Space(S.getIslCtx(), 1, 0); 315 316 std::string param_name = getName(); 317 param_name += "_fortranarr_size"; 318 isl::id IdPwAff = isl::id::alloc(S.getIslCtx(), param_name, this); 319 320 Space = Space.set_dim_id(isl::dim::param, 0, IdPwAff); 321 isl::pw_aff PwAff = 322 isl::aff::var_on_domain(isl::local_space(Space), isl::dim::param, 0); 323 324 DimensionSizesPw[0] = PwAff; 325 } 326 327 bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes, 328 bool CheckConsistency) { 329 int SharedDims = std::min(NewSizes.size(), DimensionSizes.size()); 330 int ExtraDimsNew = NewSizes.size() - SharedDims; 331 int ExtraDimsOld = DimensionSizes.size() - SharedDims; 332 333 if (CheckConsistency) { 334 for (int i = 0; i < SharedDims; i++) { 335 auto *NewSize = NewSizes[i + ExtraDimsNew]; 336 auto *KnownSize = DimensionSizes[i + ExtraDimsOld]; 337 if (NewSize && KnownSize && NewSize != KnownSize) 338 return false; 339 } 340 341 if (DimensionSizes.size() >= NewSizes.size()) 342 return true; 343 } 344 345 DimensionSizes.clear(); 346 DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(), 347 NewSizes.end()); 348 DimensionSizesPw.clear(); 349 for (const SCEV *Expr : DimensionSizes) { 350 if (!Expr) { 351 DimensionSizesPw.push_back(isl::pw_aff()); 352 continue; 353 } 354 isl::pw_aff Size = S.getPwAffOnly(Expr); 355 DimensionSizesPw.push_back(Size); 356 } 357 return true; 358 } 359 360 std::string ScopArrayInfo::getName() const { return Id.get_name(); } 361 362 int ScopArrayInfo::getElemSizeInBytes() const { 363 return DL.getTypeAllocSize(ElementType); 364 } 365 366 isl::id ScopArrayInfo::getBasePtrId() const { return Id; } 367 368 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 369 LLVM_DUMP_METHOD void ScopArrayInfo::dump() const { print(errs()); } 370 #endif 371 372 void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const { 373 OS.indent(8) << *getElementType() << " " << getName(); 374 unsigned u = 0; 375 // If this is a Fortran array, then we can print the outermost dimension 376 // as a isl_pw_aff even though there is no SCEV information. 377 bool IsOutermostSizeKnown = SizeAsPwAff && FAD; 378 379 if (!IsOutermostSizeKnown && getNumberOfDimensions() > 0 && 380 !getDimensionSize(0)) { 381 OS << "[*]"; 382 u++; 383 } 384 for (; u < getNumberOfDimensions(); u++) { 385 OS << "["; 386 387 if (SizeAsPwAff) { 388 isl::pw_aff Size = getDimensionSizePw(u); 389 OS << " " << Size << " "; 390 } else { 391 OS << *getDimensionSize(u); 392 } 393 394 OS << "]"; 395 } 396 397 OS << ";"; 398 399 if (BasePtrOriginSAI) 400 OS << " [BasePtrOrigin: " << BasePtrOriginSAI->getName() << "]"; 401 402 OS << " // Element size " << getElemSizeInBytes() << "\n"; 403 } 404 405 const ScopArrayInfo * 406 ScopArrayInfo::getFromAccessFunction(isl::pw_multi_aff PMA) { 407 isl::id Id = PMA.get_tuple_id(isl::dim::out); 408 assert(!Id.is_null() && "Output dimension didn't have an ID"); 409 return getFromId(Id); 410 } 411 412 const ScopArrayInfo *ScopArrayInfo::getFromId(isl::id Id) { 413 void *User = Id.get_user(); 414 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 415 return SAI; 416 } 417 418 void MemoryAccess::wrapConstantDimensions() { 419 auto *SAI = getScopArrayInfo(); 420 isl::space ArraySpace = SAI->getSpace(); 421 isl::ctx Ctx = ArraySpace.get_ctx(); 422 unsigned DimsArray = SAI->getNumberOfDimensions(); 423 424 isl::multi_aff DivModAff = isl::multi_aff::identity( 425 ArraySpace.map_from_domain_and_range(ArraySpace)); 426 isl::local_space LArraySpace = isl::local_space(ArraySpace); 427 428 // Begin with last dimension, to iteratively carry into higher dimensions. 429 for (int i = DimsArray - 1; i > 0; i--) { 430 auto *DimSize = SAI->getDimensionSize(i); 431 auto *DimSizeCst = dyn_cast<SCEVConstant>(DimSize); 432 433 // This transformation is not applicable to dimensions with dynamic size. 434 if (!DimSizeCst) 435 continue; 436 437 // This transformation is not applicable to dimensions of size zero. 438 if (DimSize->isZero()) 439 continue; 440 441 isl::val DimSizeVal = 442 valFromAPInt(Ctx.get(), DimSizeCst->getAPInt(), false); 443 isl::aff Var = isl::aff::var_on_domain(LArraySpace, isl::dim::set, i); 444 isl::aff PrevVar = 445 isl::aff::var_on_domain(LArraySpace, isl::dim::set, i - 1); 446 447 // Compute: index % size 448 // Modulo must apply in the divide of the previous iteration, if any. 449 isl::aff Modulo = Var.mod(DimSizeVal); 450 Modulo = Modulo.pullback(DivModAff); 451 452 // Compute: floor(index / size) 453 isl::aff Divide = Var.div(isl::aff(LArraySpace, DimSizeVal)); 454 Divide = Divide.floor(); 455 Divide = Divide.add(PrevVar); 456 Divide = Divide.pullback(DivModAff); 457 458 // Apply Modulo and Divide. 459 DivModAff = DivModAff.set_aff(i, Modulo); 460 DivModAff = DivModAff.set_aff(i - 1, Divide); 461 } 462 463 // Apply all modulo/divides on the accesses. 464 isl::map Relation = AccessRelation; 465 Relation = Relation.apply_range(isl::map::from_multi_aff(DivModAff)); 466 Relation = Relation.detect_equalities(); 467 AccessRelation = Relation; 468 } 469 470 void MemoryAccess::updateDimensionality() { 471 auto *SAI = getScopArrayInfo(); 472 isl::space ArraySpace = SAI->getSpace(); 473 isl::space AccessSpace = AccessRelation.get_space().range(); 474 isl::ctx Ctx = ArraySpace.get_ctx(); 475 476 auto DimsArray = ArraySpace.dim(isl::dim::set); 477 auto DimsAccess = AccessSpace.dim(isl::dim::set); 478 auto DimsMissing = DimsArray - DimsAccess; 479 480 auto *BB = getStatement()->getEntryBlock(); 481 auto &DL = BB->getModule()->getDataLayout(); 482 unsigned ArrayElemSize = SAI->getElemSizeInBytes(); 483 unsigned ElemBytes = DL.getTypeAllocSize(getElementType()); 484 485 isl::map Map = isl::map::from_domain_and_range( 486 isl::set::universe(AccessSpace), isl::set::universe(ArraySpace)); 487 488 for (auto i : seq<isl_size>(0, DimsMissing)) 489 Map = Map.fix_si(isl::dim::out, i, 0); 490 491 for (auto i : seq<isl_size>(DimsMissing, DimsArray)) 492 Map = Map.equate(isl::dim::in, i - DimsMissing, isl::dim::out, i); 493 494 AccessRelation = AccessRelation.apply_range(Map); 495 496 // For the non delinearized arrays, divide the access function of the last 497 // subscript by the size of the elements in the array. 498 // 499 // A stride one array access in C expressed as A[i] is expressed in 500 // LLVM-IR as something like A[i * elementsize]. This hides the fact that 501 // two subsequent values of 'i' index two values that are stored next to 502 // each other in memory. By this division we make this characteristic 503 // obvious again. If the base pointer was accessed with offsets not divisible 504 // by the accesses element size, we will have chosen a smaller ArrayElemSize 505 // that divides the offsets of all accesses to this base pointer. 506 if (DimsAccess == 1) { 507 isl::val V = isl::val(Ctx, ArrayElemSize); 508 AccessRelation = AccessRelation.floordiv_val(V); 509 } 510 511 // We currently do this only if we added at least one dimension, which means 512 // some dimension's indices have not been specified, an indicator that some 513 // index values have been added together. 514 // TODO: Investigate general usefulness; Effect on unit tests is to make index 515 // expressions more complicated. 516 if (DimsMissing) 517 wrapConstantDimensions(); 518 519 if (!isAffine()) 520 computeBoundsOnAccessRelation(ArrayElemSize); 521 522 // Introduce multi-element accesses in case the type loaded by this memory 523 // access is larger than the canonical element type of the array. 524 // 525 // An access ((float *)A)[i] to an array char *A is modeled as 526 // {[i] -> A[o] : 4 i <= o <= 4 i + 3 527 if (ElemBytes > ArrayElemSize) { 528 assert(ElemBytes % ArrayElemSize == 0 && 529 "Loaded element size should be multiple of canonical element size"); 530 isl::map Map = isl::map::from_domain_and_range( 531 isl::set::universe(ArraySpace), isl::set::universe(ArraySpace)); 532 for (auto i : seq<isl_size>(0, DimsArray - 1)) 533 Map = Map.equate(isl::dim::in, i, isl::dim::out, i); 534 535 isl::constraint C; 536 isl::local_space LS; 537 538 LS = isl::local_space(Map.get_space()); 539 int Num = ElemBytes / getScopArrayInfo()->getElemSizeInBytes(); 540 541 C = isl::constraint::alloc_inequality(LS); 542 C = C.set_constant_val(isl::val(Ctx, Num - 1)); 543 C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, 1); 544 C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, -1); 545 Map = Map.add_constraint(C); 546 547 C = isl::constraint::alloc_inequality(LS); 548 C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, -1); 549 C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, 1); 550 C = C.set_constant_val(isl::val(Ctx, 0)); 551 Map = Map.add_constraint(C); 552 AccessRelation = AccessRelation.apply_range(Map); 553 } 554 } 555 556 const std::string 557 MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) { 558 switch (RT) { 559 case MemoryAccess::RT_NONE: 560 llvm_unreachable("Requested a reduction operator string for a memory " 561 "access which isn't a reduction"); 562 case MemoryAccess::RT_ADD: 563 return "+"; 564 case MemoryAccess::RT_MUL: 565 return "*"; 566 case MemoryAccess::RT_BOR: 567 return "|"; 568 case MemoryAccess::RT_BXOR: 569 return "^"; 570 case MemoryAccess::RT_BAND: 571 return "&"; 572 } 573 llvm_unreachable("Unknown reduction type"); 574 } 575 576 const ScopArrayInfo *MemoryAccess::getOriginalScopArrayInfo() const { 577 isl::id ArrayId = getArrayId(); 578 void *User = ArrayId.get_user(); 579 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 580 return SAI; 581 } 582 583 const ScopArrayInfo *MemoryAccess::getLatestScopArrayInfo() const { 584 isl::id ArrayId = getLatestArrayId(); 585 void *User = ArrayId.get_user(); 586 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User); 587 return SAI; 588 } 589 590 isl::id MemoryAccess::getOriginalArrayId() const { 591 return AccessRelation.get_tuple_id(isl::dim::out); 592 } 593 594 isl::id MemoryAccess::getLatestArrayId() const { 595 if (!hasNewAccessRelation()) 596 return getOriginalArrayId(); 597 return NewAccessRelation.get_tuple_id(isl::dim::out); 598 } 599 600 isl::map MemoryAccess::getAddressFunction() const { 601 return getAccessRelation().lexmin(); 602 } 603 604 isl::pw_multi_aff 605 MemoryAccess::applyScheduleToAccessRelation(isl::union_map USchedule) const { 606 isl::map Schedule, ScheduledAccRel; 607 isl::union_set UDomain; 608 609 UDomain = getStatement()->getDomain(); 610 USchedule = USchedule.intersect_domain(UDomain); 611 Schedule = isl::map::from_union_map(USchedule); 612 ScheduledAccRel = getAddressFunction().apply_domain(Schedule); 613 return isl::pw_multi_aff::from_map(ScheduledAccRel); 614 } 615 616 isl::map MemoryAccess::getOriginalAccessRelation() const { 617 return AccessRelation; 618 } 619 620 std::string MemoryAccess::getOriginalAccessRelationStr() const { 621 return AccessRelation.to_str(); 622 } 623 624 isl::space MemoryAccess::getOriginalAccessRelationSpace() const { 625 return AccessRelation.get_space(); 626 } 627 628 isl::map MemoryAccess::getNewAccessRelation() const { 629 return NewAccessRelation; 630 } 631 632 std::string MemoryAccess::getNewAccessRelationStr() const { 633 return NewAccessRelation.to_str(); 634 } 635 636 std::string MemoryAccess::getAccessRelationStr() const { 637 return getAccessRelation().to_str(); 638 } 639 640 isl::basic_map MemoryAccess::createBasicAccessMap(ScopStmt *Statement) { 641 isl::space Space = isl::space(Statement->getIslCtx(), 0, 1); 642 Space = Space.align_params(Statement->getDomainSpace()); 643 644 return isl::basic_map::from_domain_and_range( 645 isl::basic_set::universe(Statement->getDomainSpace()), 646 isl::basic_set::universe(Space)); 647 } 648 649 // Formalize no out-of-bound access assumption 650 // 651 // When delinearizing array accesses we optimistically assume that the 652 // delinearized accesses do not access out of bound locations (the subscript 653 // expression of each array evaluates for each statement instance that is 654 // executed to a value that is larger than zero and strictly smaller than the 655 // size of the corresponding dimension). The only exception is the outermost 656 // dimension for which we do not need to assume any upper bound. At this point 657 // we formalize this assumption to ensure that at code generation time the 658 // relevant run-time checks can be generated. 659 // 660 // To find the set of constraints necessary to avoid out of bound accesses, we 661 // first build the set of data locations that are not within array bounds. We 662 // then apply the reverse access relation to obtain the set of iterations that 663 // may contain invalid accesses and reduce this set of iterations to the ones 664 // that are actually executed by intersecting them with the domain of the 665 // statement. If we now project out all loop dimensions, we obtain a set of 666 // parameters that may cause statement instances to be executed that may 667 // possibly yield out of bound memory accesses. The complement of these 668 // constraints is the set of constraints that needs to be assumed to ensure such 669 // statement instances are never executed. 670 isl::set MemoryAccess::assumeNoOutOfBound() { 671 auto *SAI = getScopArrayInfo(); 672 isl::space Space = getOriginalAccessRelationSpace().range(); 673 isl::set Outside = isl::set::empty(Space); 674 for (int i = 1, Size = Space.dim(isl::dim::set); i < Size; ++i) { 675 isl::local_space LS(Space); 676 isl::pw_aff Var = isl::pw_aff::var_on_domain(LS, isl::dim::set, i); 677 isl::pw_aff Zero = isl::pw_aff(LS); 678 679 isl::set DimOutside = Var.lt_set(Zero); 680 isl::pw_aff SizeE = SAI->getDimensionSizePw(i); 681 SizeE = SizeE.add_dims(isl::dim::in, Space.dim(isl::dim::set)); 682 SizeE = SizeE.set_tuple_id(isl::dim::in, Space.get_tuple_id(isl::dim::set)); 683 DimOutside = DimOutside.unite(SizeE.le_set(Var)); 684 685 Outside = Outside.unite(DimOutside); 686 } 687 688 Outside = Outside.apply(getAccessRelation().reverse()); 689 Outside = Outside.intersect(Statement->getDomain()); 690 Outside = Outside.params(); 691 692 // Remove divs to avoid the construction of overly complicated assumptions. 693 // Doing so increases the set of parameter combinations that are assumed to 694 // not appear. This is always save, but may make the resulting run-time check 695 // bail out more often than strictly necessary. 696 Outside = Outside.remove_divs(); 697 Outside = Outside.complement(); 698 699 if (!PollyPreciseInbounds) 700 Outside = Outside.gist_params(Statement->getDomain().params()); 701 return Outside; 702 } 703 704 void MemoryAccess::buildMemIntrinsicAccessRelation() { 705 assert(isMemoryIntrinsic()); 706 assert(Subscripts.size() == 2 && Sizes.size() == 1); 707 708 isl::pw_aff SubscriptPWA = getPwAff(Subscripts[0]); 709 isl::map SubscriptMap = isl::map::from_pw_aff(SubscriptPWA); 710 711 isl::map LengthMap; 712 if (Subscripts[1] == nullptr) { 713 LengthMap = isl::map::universe(SubscriptMap.get_space()); 714 } else { 715 isl::pw_aff LengthPWA = getPwAff(Subscripts[1]); 716 LengthMap = isl::map::from_pw_aff(LengthPWA); 717 isl::space RangeSpace = LengthMap.get_space().range(); 718 LengthMap = LengthMap.apply_range(isl::map::lex_gt(RangeSpace)); 719 } 720 LengthMap = LengthMap.lower_bound_si(isl::dim::out, 0, 0); 721 LengthMap = LengthMap.align_params(SubscriptMap.get_space()); 722 SubscriptMap = SubscriptMap.align_params(LengthMap.get_space()); 723 LengthMap = LengthMap.sum(SubscriptMap); 724 AccessRelation = 725 LengthMap.set_tuple_id(isl::dim::in, getStatement()->getDomainId()); 726 } 727 728 void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) { 729 ScalarEvolution *SE = Statement->getParent()->getSE(); 730 731 auto MAI = MemAccInst(getAccessInstruction()); 732 if (isa<MemIntrinsic>(MAI)) 733 return; 734 735 Value *Ptr = MAI.getPointerOperand(); 736 if (!Ptr || !SE->isSCEVable(Ptr->getType())) 737 return; 738 739 auto *PtrSCEV = SE->getSCEV(Ptr); 740 if (isa<SCEVCouldNotCompute>(PtrSCEV)) 741 return; 742 743 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV); 744 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV)) 745 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV); 746 747 const ConstantRange &Range = SE->getSignedRange(PtrSCEV); 748 if (Range.isFullSet()) 749 return; 750 751 if (Range.isUpperWrapped() || Range.isSignWrappedSet()) 752 return; 753 754 bool isWrapping = Range.isSignWrappedSet(); 755 756 unsigned BW = Range.getBitWidth(); 757 const auto One = APInt(BW, 1); 758 const auto LB = isWrapping ? Range.getLower() : Range.getSignedMin(); 759 const auto UB = isWrapping ? (Range.getUpper() - One) : Range.getSignedMax(); 760 761 auto Min = LB.sdiv(APInt(BW, ElementSize)); 762 auto Max = UB.sdiv(APInt(BW, ElementSize)) + One; 763 764 assert(Min.sle(Max) && "Minimum expected to be less or equal than max"); 765 766 isl::map Relation = AccessRelation; 767 isl::set AccessRange = Relation.range(); 768 AccessRange = addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0, 769 isl::dim::set); 770 AccessRelation = Relation.intersect_range(AccessRange); 771 } 772 773 void MemoryAccess::foldAccessRelation() { 774 if (Sizes.size() < 2 || isa<SCEVConstant>(Sizes[1])) 775 return; 776 777 int Size = Subscripts.size(); 778 779 isl::map NewAccessRelation = AccessRelation; 780 781 for (int i = Size - 2; i >= 0; --i) { 782 isl::space Space; 783 isl::map MapOne, MapTwo; 784 isl::pw_aff DimSize = getPwAff(Sizes[i + 1]); 785 786 isl::space SpaceSize = DimSize.get_space(); 787 isl::id ParamId = SpaceSize.get_dim_id(isl::dim::param, 0); 788 789 Space = AccessRelation.get_space(); 790 Space = Space.range().map_from_set(); 791 Space = Space.align_params(SpaceSize); 792 793 int ParamLocation = Space.find_dim_by_id(isl::dim::param, ParamId); 794 795 MapOne = isl::map::universe(Space); 796 for (int j = 0; j < Size; ++j) 797 MapOne = MapOne.equate(isl::dim::in, j, isl::dim::out, j); 798 MapOne = MapOne.lower_bound_si(isl::dim::in, i + 1, 0); 799 800 MapTwo = isl::map::universe(Space); 801 for (int j = 0; j < Size; ++j) 802 if (j < i || j > i + 1) 803 MapTwo = MapTwo.equate(isl::dim::in, j, isl::dim::out, j); 804 805 isl::local_space LS(Space); 806 isl::constraint C; 807 C = isl::constraint::alloc_equality(LS); 808 C = C.set_constant_si(-1); 809 C = C.set_coefficient_si(isl::dim::in, i, 1); 810 C = C.set_coefficient_si(isl::dim::out, i, -1); 811 MapTwo = MapTwo.add_constraint(C); 812 C = isl::constraint::alloc_equality(LS); 813 C = C.set_coefficient_si(isl::dim::in, i + 1, 1); 814 C = C.set_coefficient_si(isl::dim::out, i + 1, -1); 815 C = C.set_coefficient_si(isl::dim::param, ParamLocation, 1); 816 MapTwo = MapTwo.add_constraint(C); 817 MapTwo = MapTwo.upper_bound_si(isl::dim::in, i + 1, -1); 818 819 MapOne = MapOne.unite(MapTwo); 820 NewAccessRelation = NewAccessRelation.apply_range(MapOne); 821 } 822 823 isl::id BaseAddrId = getScopArrayInfo()->getBasePtrId(); 824 isl::space Space = Statement->getDomainSpace(); 825 NewAccessRelation = NewAccessRelation.set_tuple_id( 826 isl::dim::in, Space.get_tuple_id(isl::dim::set)); 827 NewAccessRelation = NewAccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 828 NewAccessRelation = NewAccessRelation.gist_domain(Statement->getDomain()); 829 830 // Access dimension folding might in certain cases increase the number of 831 // disjuncts in the memory access, which can possibly complicate the generated 832 // run-time checks and can lead to costly compilation. 833 if (!PollyPreciseFoldAccesses && 834 NewAccessRelation.n_basic_map() > AccessRelation.n_basic_map()) { 835 } else { 836 AccessRelation = NewAccessRelation; 837 } 838 } 839 840 void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) { 841 assert(AccessRelation.is_null() && "AccessRelation already built"); 842 843 // Initialize the invalid domain which describes all iterations for which the 844 // access relation is not modeled correctly. 845 isl::set StmtInvalidDomain = getStatement()->getInvalidDomain(); 846 InvalidDomain = isl::set::empty(StmtInvalidDomain.get_space()); 847 848 isl::ctx Ctx = Id.get_ctx(); 849 isl::id BaseAddrId = SAI->getBasePtrId(); 850 851 if (getAccessInstruction() && isa<MemIntrinsic>(getAccessInstruction())) { 852 buildMemIntrinsicAccessRelation(); 853 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 854 return; 855 } 856 857 if (!isAffine()) { 858 // We overapproximate non-affine accesses with a possible access to the 859 // whole array. For read accesses it does not make a difference, if an 860 // access must or may happen. However, for write accesses it is important to 861 // differentiate between writes that must happen and writes that may happen. 862 if (AccessRelation.is_null()) 863 AccessRelation = createBasicAccessMap(Statement); 864 865 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 866 return; 867 } 868 869 isl::space Space = isl::space(Ctx, 0, Statement->getNumIterators(), 0); 870 AccessRelation = isl::map::universe(Space); 871 872 for (int i = 0, Size = Subscripts.size(); i < Size; ++i) { 873 isl::pw_aff Affine = getPwAff(Subscripts[i]); 874 isl::map SubscriptMap = isl::map::from_pw_aff(Affine); 875 AccessRelation = AccessRelation.flat_range_product(SubscriptMap); 876 } 877 878 Space = Statement->getDomainSpace(); 879 AccessRelation = AccessRelation.set_tuple_id( 880 isl::dim::in, Space.get_tuple_id(isl::dim::set)); 881 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId); 882 883 AccessRelation = AccessRelation.gist_domain(Statement->getDomain()); 884 } 885 886 MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst, 887 AccessType AccType, Value *BaseAddress, 888 Type *ElementType, bool Affine, 889 ArrayRef<const SCEV *> Subscripts, 890 ArrayRef<const SCEV *> Sizes, Value *AccessValue, 891 MemoryKind Kind) 892 : Kind(Kind), AccType(AccType), Statement(Stmt), InvalidDomain(), 893 BaseAddr(BaseAddress), ElementType(ElementType), 894 Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst), 895 AccessValue(AccessValue), IsAffine(Affine), 896 Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(), 897 NewAccessRelation(), FAD(nullptr) { 898 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"}; 899 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size()); 900 901 std::string IdName = Stmt->getBaseName() + Access; 902 Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this); 903 } 904 905 MemoryAccess::MemoryAccess(ScopStmt *Stmt, AccessType AccType, isl::map AccRel) 906 : Kind(MemoryKind::Array), AccType(AccType), Statement(Stmt), 907 InvalidDomain(), AccessRelation(), NewAccessRelation(AccRel), 908 FAD(nullptr) { 909 isl::id ArrayInfoId = NewAccessRelation.get_tuple_id(isl::dim::out); 910 auto *SAI = ScopArrayInfo::getFromId(ArrayInfoId); 911 Sizes.push_back(nullptr); 912 for (unsigned i = 1; i < SAI->getNumberOfDimensions(); i++) 913 Sizes.push_back(SAI->getDimensionSize(i)); 914 ElementType = SAI->getElementType(); 915 BaseAddr = SAI->getBasePtr(); 916 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"}; 917 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size()); 918 919 std::string IdName = Stmt->getBaseName() + Access; 920 Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this); 921 } 922 923 MemoryAccess::~MemoryAccess() = default; 924 925 void MemoryAccess::realignParams() { 926 isl::set Ctx = Statement->getParent()->getContext(); 927 InvalidDomain = InvalidDomain.gist_params(Ctx); 928 AccessRelation = AccessRelation.gist_params(Ctx); 929 930 // Predictable parameter order is required for JSON imports. Ensure alignment 931 // by explicitly calling align_params. 932 isl::space CtxSpace = Ctx.get_space(); 933 InvalidDomain = InvalidDomain.align_params(CtxSpace); 934 AccessRelation = AccessRelation.align_params(CtxSpace); 935 } 936 937 const std::string MemoryAccess::getReductionOperatorStr() const { 938 return MemoryAccess::getReductionOperatorStr(getReductionType()); 939 } 940 941 isl::id MemoryAccess::getId() const { return Id; } 942 943 raw_ostream &polly::operator<<(raw_ostream &OS, 944 MemoryAccess::ReductionType RT) { 945 if (RT == MemoryAccess::RT_NONE) 946 OS << "NONE"; 947 else 948 OS << MemoryAccess::getReductionOperatorStr(RT); 949 return OS; 950 } 951 952 void MemoryAccess::setFortranArrayDescriptor(Value *FAD) { this->FAD = FAD; } 953 954 void MemoryAccess::print(raw_ostream &OS) const { 955 switch (AccType) { 956 case READ: 957 OS.indent(12) << "ReadAccess :=\t"; 958 break; 959 case MUST_WRITE: 960 OS.indent(12) << "MustWriteAccess :=\t"; 961 break; 962 case MAY_WRITE: 963 OS.indent(12) << "MayWriteAccess :=\t"; 964 break; 965 } 966 967 OS << "[Reduction Type: " << getReductionType() << "] "; 968 969 if (FAD) { 970 OS << "[Fortran array descriptor: " << FAD->getName(); 971 OS << "] "; 972 }; 973 974 OS << "[Scalar: " << isScalarKind() << "]\n"; 975 OS.indent(16) << getOriginalAccessRelationStr() << ";\n"; 976 if (hasNewAccessRelation()) 977 OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n"; 978 } 979 980 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 981 LLVM_DUMP_METHOD void MemoryAccess::dump() const { print(errs()); } 982 #endif 983 984 isl::pw_aff MemoryAccess::getPwAff(const SCEV *E) { 985 auto *Stmt = getStatement(); 986 PWACtx PWAC = Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock()); 987 isl::set StmtDom = getStatement()->getDomain(); 988 StmtDom = StmtDom.reset_tuple_id(); 989 isl::set NewInvalidDom = StmtDom.intersect(PWAC.second); 990 InvalidDomain = InvalidDomain.unite(NewInvalidDom); 991 return PWAC.first; 992 } 993 994 // Create a map in the size of the provided set domain, that maps from the 995 // one element of the provided set domain to another element of the provided 996 // set domain. 997 // The mapping is limited to all points that are equal in all but the last 998 // dimension and for which the last dimension of the input is strict smaller 999 // than the last dimension of the output. 1000 // 1001 // getEqualAndLarger(set[i0, i1, ..., iX]): 1002 // 1003 // set[i0, i1, ..., iX] -> set[o0, o1, ..., oX] 1004 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX 1005 // 1006 static isl::map getEqualAndLarger(isl::space SetDomain) { 1007 isl::space Space = SetDomain.map_from_set(); 1008 isl::map Map = isl::map::universe(Space); 1009 unsigned lastDimension = Map.dim(isl::dim::in) - 1; 1010 1011 // Set all but the last dimension to be equal for the input and output 1012 // 1013 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX] 1014 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1) 1015 for (unsigned i = 0; i < lastDimension; ++i) 1016 Map = Map.equate(isl::dim::in, i, isl::dim::out, i); 1017 1018 // Set the last dimension of the input to be strict smaller than the 1019 // last dimension of the output. 1020 // 1021 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX 1022 Map = Map.order_lt(isl::dim::in, lastDimension, isl::dim::out, lastDimension); 1023 return Map; 1024 } 1025 1026 isl::set MemoryAccess::getStride(isl::map Schedule) const { 1027 isl::map AccessRelation = getAccessRelation(); 1028 isl::space Space = Schedule.get_space().range(); 1029 isl::map NextScatt = getEqualAndLarger(Space); 1030 1031 Schedule = Schedule.reverse(); 1032 NextScatt = NextScatt.lexmin(); 1033 1034 NextScatt = NextScatt.apply_range(Schedule); 1035 NextScatt = NextScatt.apply_range(AccessRelation); 1036 NextScatt = NextScatt.apply_domain(Schedule); 1037 NextScatt = NextScatt.apply_domain(AccessRelation); 1038 1039 isl::set Deltas = NextScatt.deltas(); 1040 return Deltas; 1041 } 1042 1043 bool MemoryAccess::isStrideX(isl::map Schedule, int StrideWidth) const { 1044 isl::set Stride, StrideX; 1045 bool IsStrideX; 1046 1047 Stride = getStride(Schedule); 1048 StrideX = isl::set::universe(Stride.get_space()); 1049 for (auto i : seq<isl_size>(0, StrideX.dim(isl::dim::set) - 1)) 1050 StrideX = StrideX.fix_si(isl::dim::set, i, 0); 1051 StrideX = StrideX.fix_si(isl::dim::set, StrideX.dim(isl::dim::set) - 1, 1052 StrideWidth); 1053 IsStrideX = Stride.is_subset(StrideX); 1054 1055 return IsStrideX; 1056 } 1057 1058 bool MemoryAccess::isStrideZero(isl::map Schedule) const { 1059 return isStrideX(Schedule, 0); 1060 } 1061 1062 bool MemoryAccess::isStrideOne(isl::map Schedule) const { 1063 return isStrideX(Schedule, 1); 1064 } 1065 1066 void MemoryAccess::setAccessRelation(isl::map NewAccess) { 1067 AccessRelation = NewAccess; 1068 } 1069 1070 void MemoryAccess::setNewAccessRelation(isl::map NewAccess) { 1071 assert(!NewAccess.is_null()); 1072 1073 #ifndef NDEBUG 1074 // Check domain space compatibility. 1075 isl::space NewSpace = NewAccess.get_space(); 1076 isl::space NewDomainSpace = NewSpace.domain(); 1077 isl::space OriginalDomainSpace = getStatement()->getDomainSpace(); 1078 assert(OriginalDomainSpace.has_equal_tuples(NewDomainSpace)); 1079 1080 // Reads must be executed unconditionally. Writes might be executed in a 1081 // subdomain only. 1082 if (isRead()) { 1083 // Check whether there is an access for every statement instance. 1084 isl::set StmtDomain = getStatement()->getDomain(); 1085 isl::set DefinedContext = 1086 getStatement()->getParent()->getBestKnownDefinedBehaviorContext(); 1087 StmtDomain = StmtDomain.intersect_params(DefinedContext); 1088 isl::set NewDomain = NewAccess.domain(); 1089 assert(!StmtDomain.is_subset(NewDomain).is_false() && 1090 "Partial READ accesses not supported"); 1091 } 1092 1093 isl::space NewAccessSpace = NewAccess.get_space(); 1094 assert(NewAccessSpace.has_tuple_id(isl::dim::set) && 1095 "Must specify the array that is accessed"); 1096 isl::id NewArrayId = NewAccessSpace.get_tuple_id(isl::dim::set); 1097 auto *SAI = static_cast<ScopArrayInfo *>(NewArrayId.get_user()); 1098 assert(SAI && "Must set a ScopArrayInfo"); 1099 1100 if (SAI->isArrayKind() && SAI->getBasePtrOriginSAI()) { 1101 InvariantEquivClassTy *EqClass = 1102 getStatement()->getParent()->lookupInvariantEquivClass( 1103 SAI->getBasePtr()); 1104 assert(EqClass && 1105 "Access functions to indirect arrays must have an invariant and " 1106 "hoisted base pointer"); 1107 } 1108 1109 // Check whether access dimensions correspond to number of dimensions of the 1110 // accesses array. 1111 isl_size Dims = SAI->getNumberOfDimensions(); 1112 assert(NewAccessSpace.dim(isl::dim::set) == Dims && 1113 "Access dims must match array dims"); 1114 #endif 1115 1116 NewAccess = NewAccess.gist_params(getStatement()->getParent()->getContext()); 1117 NewAccess = NewAccess.gist_domain(getStatement()->getDomain()); 1118 NewAccessRelation = NewAccess; 1119 } 1120 1121 bool MemoryAccess::isLatestPartialAccess() const { 1122 isl::set StmtDom = getStatement()->getDomain(); 1123 isl::set AccDom = getLatestAccessRelation().domain(); 1124 1125 return !StmtDom.is_subset(AccDom); 1126 } 1127 1128 //===----------------------------------------------------------------------===// 1129 1130 isl::map ScopStmt::getSchedule() const { 1131 isl::set Domain = getDomain(); 1132 if (Domain.is_empty()) 1133 return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace()))); 1134 auto Schedule = getParent()->getSchedule(); 1135 if (Schedule.is_null()) 1136 return {}; 1137 Schedule = Schedule.intersect_domain(isl::union_set(Domain)); 1138 if (Schedule.is_empty()) 1139 return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace()))); 1140 isl::map M = M.from_union_map(Schedule); 1141 M = M.coalesce(); 1142 M = M.gist_domain(Domain); 1143 M = M.coalesce(); 1144 return M; 1145 } 1146 1147 void ScopStmt::restrictDomain(isl::set NewDomain) { 1148 assert(NewDomain.is_subset(Domain) && 1149 "New domain is not a subset of old domain!"); 1150 Domain = NewDomain; 1151 } 1152 1153 void ScopStmt::addAccess(MemoryAccess *Access, bool Prepend) { 1154 Instruction *AccessInst = Access->getAccessInstruction(); 1155 1156 if (Access->isArrayKind()) { 1157 MemoryAccessList &MAL = InstructionToAccess[AccessInst]; 1158 MAL.emplace_front(Access); 1159 } else if (Access->isValueKind() && Access->isWrite()) { 1160 Instruction *AccessVal = cast<Instruction>(Access->getAccessValue()); 1161 assert(!ValueWrites.lookup(AccessVal)); 1162 1163 ValueWrites[AccessVal] = Access; 1164 } else if (Access->isValueKind() && Access->isRead()) { 1165 Value *AccessVal = Access->getAccessValue(); 1166 assert(!ValueReads.lookup(AccessVal)); 1167 1168 ValueReads[AccessVal] = Access; 1169 } else if (Access->isAnyPHIKind() && Access->isWrite()) { 1170 PHINode *PHI = cast<PHINode>(Access->getAccessValue()); 1171 assert(!PHIWrites.lookup(PHI)); 1172 1173 PHIWrites[PHI] = Access; 1174 } else if (Access->isAnyPHIKind() && Access->isRead()) { 1175 PHINode *PHI = cast<PHINode>(Access->getAccessValue()); 1176 assert(!PHIReads.lookup(PHI)); 1177 1178 PHIReads[PHI] = Access; 1179 } 1180 1181 if (Prepend) { 1182 MemAccs.insert(MemAccs.begin(), Access); 1183 return; 1184 } 1185 MemAccs.push_back(Access); 1186 } 1187 1188 void ScopStmt::realignParams() { 1189 for (MemoryAccess *MA : *this) 1190 MA->realignParams(); 1191 1192 isl::set Ctx = Parent.getContext(); 1193 InvalidDomain = InvalidDomain.gist_params(Ctx); 1194 Domain = Domain.gist_params(Ctx); 1195 1196 // Predictable parameter order is required for JSON imports. Ensure alignment 1197 // by explicitly calling align_params. 1198 isl::space CtxSpace = Ctx.get_space(); 1199 InvalidDomain = InvalidDomain.align_params(CtxSpace); 1200 Domain = Domain.align_params(CtxSpace); 1201 } 1202 1203 ScopStmt::ScopStmt(Scop &parent, Region &R, StringRef Name, 1204 Loop *SurroundingLoop, 1205 std::vector<Instruction *> EntryBlockInstructions) 1206 : Parent(parent), InvalidDomain(), Domain(), R(&R), Build(), BaseName(Name), 1207 SurroundingLoop(SurroundingLoop), Instructions(EntryBlockInstructions) {} 1208 1209 ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, StringRef Name, 1210 Loop *SurroundingLoop, 1211 std::vector<Instruction *> Instructions) 1212 : Parent(parent), InvalidDomain(), Domain(), BB(&bb), Build(), 1213 BaseName(Name), SurroundingLoop(SurroundingLoop), 1214 Instructions(Instructions) {} 1215 1216 ScopStmt::ScopStmt(Scop &parent, isl::map SourceRel, isl::map TargetRel, 1217 isl::set NewDomain) 1218 : Parent(parent), InvalidDomain(), Domain(NewDomain), Build() { 1219 BaseName = getIslCompatibleName("CopyStmt_", "", 1220 std::to_string(parent.getCopyStmtsNum())); 1221 isl::id Id = isl::id::alloc(getIslCtx(), getBaseName(), this); 1222 Domain = Domain.set_tuple_id(Id); 1223 TargetRel = TargetRel.set_tuple_id(isl::dim::in, Id); 1224 auto *Access = 1225 new MemoryAccess(this, MemoryAccess::AccessType::MUST_WRITE, TargetRel); 1226 parent.addAccessFunction(Access); 1227 addAccess(Access); 1228 SourceRel = SourceRel.set_tuple_id(isl::dim::in, Id); 1229 Access = new MemoryAccess(this, MemoryAccess::AccessType::READ, SourceRel); 1230 parent.addAccessFunction(Access); 1231 addAccess(Access); 1232 } 1233 1234 ScopStmt::~ScopStmt() = default; 1235 1236 std::string ScopStmt::getDomainStr() const { return Domain.to_str(); } 1237 1238 std::string ScopStmt::getScheduleStr() const { 1239 auto *S = getSchedule().release(); 1240 if (!S) 1241 return {}; 1242 auto Str = stringFromIslObj(S); 1243 isl_map_free(S); 1244 return Str; 1245 } 1246 1247 void ScopStmt::setInvalidDomain(isl::set ID) { InvalidDomain = ID; } 1248 1249 BasicBlock *ScopStmt::getEntryBlock() const { 1250 if (isBlockStmt()) 1251 return getBasicBlock(); 1252 return getRegion()->getEntry(); 1253 } 1254 1255 unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); } 1256 1257 const char *ScopStmt::getBaseName() const { return BaseName.c_str(); } 1258 1259 Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const { 1260 return NestLoops[Dimension]; 1261 } 1262 1263 isl::ctx ScopStmt::getIslCtx() const { return Parent.getIslCtx(); } 1264 1265 isl::set ScopStmt::getDomain() const { return Domain; } 1266 1267 isl::space ScopStmt::getDomainSpace() const { return Domain.get_space(); } 1268 1269 isl::id ScopStmt::getDomainId() const { return Domain.get_tuple_id(); } 1270 1271 void ScopStmt::printInstructions(raw_ostream &OS) const { 1272 OS << "Instructions {\n"; 1273 1274 for (Instruction *Inst : Instructions) 1275 OS.indent(16) << *Inst << "\n"; 1276 1277 OS.indent(12) << "}\n"; 1278 } 1279 1280 void ScopStmt::print(raw_ostream &OS, bool PrintInstructions) const { 1281 OS << "\t" << getBaseName() << "\n"; 1282 OS.indent(12) << "Domain :=\n"; 1283 1284 if (!Domain.is_null()) { 1285 OS.indent(16) << getDomainStr() << ";\n"; 1286 } else 1287 OS.indent(16) << "n/a\n"; 1288 1289 OS.indent(12) << "Schedule :=\n"; 1290 1291 if (!Domain.is_null()) { 1292 OS.indent(16) << getScheduleStr() << ";\n"; 1293 } else 1294 OS.indent(16) << "n/a\n"; 1295 1296 for (MemoryAccess *Access : MemAccs) 1297 Access->print(OS); 1298 1299 if (PrintInstructions) 1300 printInstructions(OS.indent(12)); 1301 } 1302 1303 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1304 LLVM_DUMP_METHOD void ScopStmt::dump() const { print(dbgs(), true); } 1305 #endif 1306 1307 void ScopStmt::removeAccessData(MemoryAccess *MA) { 1308 if (MA->isRead() && MA->isOriginalValueKind()) { 1309 bool Found = ValueReads.erase(MA->getAccessValue()); 1310 (void)Found; 1311 assert(Found && "Expected access data not found"); 1312 } 1313 if (MA->isWrite() && MA->isOriginalValueKind()) { 1314 bool Found = ValueWrites.erase(cast<Instruction>(MA->getAccessValue())); 1315 (void)Found; 1316 assert(Found && "Expected access data not found"); 1317 } 1318 if (MA->isWrite() && MA->isOriginalAnyPHIKind()) { 1319 bool Found = PHIWrites.erase(cast<PHINode>(MA->getAccessInstruction())); 1320 (void)Found; 1321 assert(Found && "Expected access data not found"); 1322 } 1323 if (MA->isRead() && MA->isOriginalAnyPHIKind()) { 1324 bool Found = PHIReads.erase(cast<PHINode>(MA->getAccessInstruction())); 1325 (void)Found; 1326 assert(Found && "Expected access data not found"); 1327 } 1328 } 1329 1330 void ScopStmt::removeMemoryAccess(MemoryAccess *MA) { 1331 // Remove the memory accesses from this statement together with all scalar 1332 // accesses that were caused by it. MemoryKind::Value READs have no access 1333 // instruction, hence would not be removed by this function. However, it is 1334 // only used for invariant LoadInst accesses, its arguments are always affine, 1335 // hence synthesizable, and therefore there are no MemoryKind::Value READ 1336 // accesses to be removed. 1337 auto Predicate = [&](MemoryAccess *Acc) { 1338 return Acc->getAccessInstruction() == MA->getAccessInstruction(); 1339 }; 1340 for (auto *MA : MemAccs) { 1341 if (Predicate(MA)) { 1342 removeAccessData(MA); 1343 Parent.removeAccessData(MA); 1344 } 1345 } 1346 MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate), 1347 MemAccs.end()); 1348 InstructionToAccess.erase(MA->getAccessInstruction()); 1349 } 1350 1351 void ScopStmt::removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting) { 1352 if (AfterHoisting) { 1353 auto MAIt = std::find(MemAccs.begin(), MemAccs.end(), MA); 1354 assert(MAIt != MemAccs.end()); 1355 MemAccs.erase(MAIt); 1356 1357 removeAccessData(MA); 1358 Parent.removeAccessData(MA); 1359 } 1360 1361 auto It = InstructionToAccess.find(MA->getAccessInstruction()); 1362 if (It != InstructionToAccess.end()) { 1363 It->second.remove(MA); 1364 if (It->second.empty()) 1365 InstructionToAccess.erase(MA->getAccessInstruction()); 1366 } 1367 } 1368 1369 MemoryAccess *ScopStmt::ensureValueRead(Value *V) { 1370 MemoryAccess *Access = lookupInputAccessOf(V); 1371 if (Access) 1372 return Access; 1373 1374 ScopArrayInfo *SAI = 1375 Parent.getOrCreateScopArrayInfo(V, V->getType(), {}, MemoryKind::Value); 1376 Access = new MemoryAccess(this, nullptr, MemoryAccess::READ, V, V->getType(), 1377 true, {}, {}, V, MemoryKind::Value); 1378 Parent.addAccessFunction(Access); 1379 Access->buildAccessRelation(SAI); 1380 addAccess(Access); 1381 Parent.addAccessData(Access); 1382 return Access; 1383 } 1384 1385 raw_ostream &polly::operator<<(raw_ostream &OS, const ScopStmt &S) { 1386 S.print(OS, PollyPrintInstructions); 1387 return OS; 1388 } 1389 1390 //===----------------------------------------------------------------------===// 1391 /// Scop class implement 1392 1393 void Scop::setContext(isl::set NewContext) { 1394 Context = NewContext.align_params(Context.get_space()); 1395 } 1396 1397 namespace { 1398 1399 /// Remap parameter values but keep AddRecs valid wrt. invariant loads. 1400 struct SCEVSensitiveParameterRewriter 1401 : public SCEVRewriteVisitor<SCEVSensitiveParameterRewriter> { 1402 const ValueToValueMap &VMap; 1403 1404 public: 1405 SCEVSensitiveParameterRewriter(const ValueToValueMap &VMap, 1406 ScalarEvolution &SE) 1407 : SCEVRewriteVisitor(SE), VMap(VMap) {} 1408 1409 static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE, 1410 const ValueToValueMap &VMap) { 1411 SCEVSensitiveParameterRewriter SSPR(VMap, SE); 1412 return SSPR.visit(E); 1413 } 1414 1415 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) { 1416 auto *Start = visit(E->getStart()); 1417 auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0), 1418 visit(E->getStepRecurrence(SE)), 1419 E->getLoop(), SCEV::FlagAnyWrap); 1420 return SE.getAddExpr(Start, AddRec); 1421 } 1422 1423 const SCEV *visitUnknown(const SCEVUnknown *E) { 1424 if (auto *NewValue = VMap.lookup(E->getValue())) 1425 return SE.getUnknown(NewValue); 1426 return E; 1427 } 1428 }; 1429 1430 /// Check whether we should remap a SCEV expression. 1431 struct SCEVFindInsideScop : public SCEVTraversal<SCEVFindInsideScop> { 1432 const ValueToValueMap &VMap; 1433 bool FoundInside = false; 1434 const Scop *S; 1435 1436 public: 1437 SCEVFindInsideScop(const ValueToValueMap &VMap, ScalarEvolution &SE, 1438 const Scop *S) 1439 : SCEVTraversal(*this), VMap(VMap), S(S) {} 1440 1441 static bool hasVariant(const SCEV *E, ScalarEvolution &SE, 1442 const ValueToValueMap &VMap, const Scop *S) { 1443 SCEVFindInsideScop SFIS(VMap, SE, S); 1444 SFIS.visitAll(E); 1445 return SFIS.FoundInside; 1446 } 1447 1448 bool follow(const SCEV *E) { 1449 if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(E)) { 1450 FoundInside |= S->getRegion().contains(AddRec->getLoop()); 1451 } else if (auto *Unknown = dyn_cast<SCEVUnknown>(E)) { 1452 if (Instruction *I = dyn_cast<Instruction>(Unknown->getValue())) 1453 FoundInside |= S->getRegion().contains(I) && !VMap.count(I); 1454 } 1455 return !FoundInside; 1456 } 1457 1458 bool isDone() { return FoundInside; } 1459 }; 1460 } // end anonymous namespace 1461 1462 const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *E) const { 1463 // Check whether it makes sense to rewrite the SCEV. (ScalarEvolution 1464 // doesn't like addition between an AddRec and an expression that 1465 // doesn't have a dominance relationship with it.) 1466 if (SCEVFindInsideScop::hasVariant(E, *SE, InvEquivClassVMap, this)) 1467 return E; 1468 1469 // Rewrite SCEV. 1470 return SCEVSensitiveParameterRewriter::rewrite(E, *SE, InvEquivClassVMap); 1471 } 1472 1473 // This table of function names is used to translate parameter names in more 1474 // human-readable names. This makes it easier to interpret Polly analysis 1475 // results. 1476 StringMap<std::string> KnownNames = { 1477 {"_Z13get_global_idj", "global_id"}, 1478 {"_Z12get_local_idj", "local_id"}, 1479 {"_Z15get_global_sizej", "global_size"}, 1480 {"_Z14get_local_sizej", "local_size"}, 1481 {"_Z12get_work_dimv", "work_dim"}, 1482 {"_Z17get_global_offsetj", "global_offset"}, 1483 {"_Z12get_group_idj", "group_id"}, 1484 {"_Z14get_num_groupsj", "num_groups"}, 1485 }; 1486 1487 static std::string getCallParamName(CallInst *Call) { 1488 std::string Result; 1489 raw_string_ostream OS(Result); 1490 std::string Name = Call->getCalledFunction()->getName().str(); 1491 1492 auto Iterator = KnownNames.find(Name); 1493 if (Iterator != KnownNames.end()) 1494 Name = "__" + Iterator->getValue(); 1495 OS << Name; 1496 for (auto &Operand : Call->arg_operands()) { 1497 ConstantInt *Op = cast<ConstantInt>(&Operand); 1498 OS << "_" << Op->getValue(); 1499 } 1500 OS.flush(); 1501 return Result; 1502 } 1503 1504 void Scop::createParameterId(const SCEV *Parameter) { 1505 assert(Parameters.count(Parameter)); 1506 assert(!ParameterIds.count(Parameter)); 1507 1508 std::string ParameterName = "p_" + std::to_string(getNumParams() - 1); 1509 1510 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) { 1511 Value *Val = ValueParameter->getValue(); 1512 CallInst *Call = dyn_cast<CallInst>(Val); 1513 1514 if (Call && isConstCall(Call)) { 1515 ParameterName = getCallParamName(Call); 1516 } else if (UseInstructionNames) { 1517 // If this parameter references a specific Value and this value has a name 1518 // we use this name as it is likely to be unique and more useful than just 1519 // a number. 1520 if (Val->hasName()) 1521 ParameterName = Val->getName().str(); 1522 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) { 1523 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets(); 1524 if (LoadOrigin->hasName()) { 1525 ParameterName += "_loaded_from_"; 1526 ParameterName += 1527 LI->getPointerOperand()->stripInBoundsOffsets()->getName(); 1528 } 1529 } 1530 } 1531 1532 ParameterName = getIslCompatibleName("", ParameterName, ""); 1533 } 1534 1535 isl::id Id = isl::id::alloc(getIslCtx(), ParameterName, 1536 const_cast<void *>((const void *)Parameter)); 1537 ParameterIds[Parameter] = Id; 1538 } 1539 1540 void Scop::addParams(const ParameterSetTy &NewParameters) { 1541 for (const SCEV *Parameter : NewParameters) { 1542 // Normalize the SCEV to get the representing element for an invariant load. 1543 Parameter = extractConstantFactor(Parameter, *SE).second; 1544 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1545 1546 if (Parameters.insert(Parameter)) 1547 createParameterId(Parameter); 1548 } 1549 } 1550 1551 isl::id Scop::getIdForParam(const SCEV *Parameter) const { 1552 // Normalize the SCEV to get the representing element for an invariant load. 1553 Parameter = getRepresentingInvariantLoadSCEV(Parameter); 1554 return ParameterIds.lookup(Parameter); 1555 } 1556 1557 bool Scop::isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const { 1558 return DT.dominates(BB, getEntry()); 1559 } 1560 1561 void Scop::buildContext() { 1562 isl::space Space = isl::space::params_alloc(getIslCtx(), 0); 1563 Context = isl::set::universe(Space); 1564 InvalidContext = isl::set::empty(Space); 1565 AssumedContext = isl::set::universe(Space); 1566 DefinedBehaviorContext = isl::set::universe(Space); 1567 } 1568 1569 void Scop::addParameterBounds() { 1570 unsigned PDim = 0; 1571 for (auto *Parameter : Parameters) { 1572 ConstantRange SRange = SE->getSignedRange(Parameter); 1573 Context = addRangeBoundsToSet(Context, SRange, PDim++, isl::dim::param); 1574 } 1575 intersectDefinedBehavior(Context, AS_ASSUMPTION); 1576 } 1577 1578 static std::vector<isl::id> getFortranArrayIds(Scop::array_range Arrays) { 1579 std::vector<isl::id> OutermostSizeIds; 1580 for (auto Array : Arrays) { 1581 // To check if an array is a Fortran array, we check if it has a isl_pw_aff 1582 // for its outermost dimension. Fortran arrays will have this since the 1583 // outermost dimension size can be picked up from their runtime description. 1584 // TODO: actually need to check if it has a FAD, but for now this works. 1585 if (Array->getNumberOfDimensions() > 0) { 1586 isl::pw_aff PwAff = Array->getDimensionSizePw(0); 1587 if (PwAff.is_null()) 1588 continue; 1589 1590 isl::id Id = PwAff.get_dim_id(isl::dim::param, 0); 1591 assert(!Id.is_null() && 1592 "Invalid Id for PwAff expression in Fortran array"); 1593 OutermostSizeIds.push_back(Id); 1594 } 1595 } 1596 return OutermostSizeIds; 1597 } 1598 1599 // The FORTRAN array size parameters are known to be non-negative. 1600 static isl::set boundFortranArrayParams(isl::set Context, 1601 Scop::array_range Arrays) { 1602 std::vector<isl::id> OutermostSizeIds; 1603 OutermostSizeIds = getFortranArrayIds(Arrays); 1604 1605 for (isl::id Id : OutermostSizeIds) { 1606 int dim = Context.find_dim_by_id(isl::dim::param, Id); 1607 Context = Context.lower_bound_si(isl::dim::param, dim, 0); 1608 } 1609 1610 return Context; 1611 } 1612 1613 void Scop::realignParams() { 1614 if (PollyIgnoreParamBounds) 1615 return; 1616 1617 // Add all parameters into a common model. 1618 isl::space Space = getFullParamSpace(); 1619 1620 // Align the parameters of all data structures to the model. 1621 Context = Context.align_params(Space); 1622 AssumedContext = AssumedContext.align_params(Space); 1623 InvalidContext = InvalidContext.align_params(Space); 1624 1625 // Bound the size of the fortran array dimensions. 1626 Context = boundFortranArrayParams(Context, arrays()); 1627 1628 // As all parameters are known add bounds to them. 1629 addParameterBounds(); 1630 1631 for (ScopStmt &Stmt : *this) 1632 Stmt.realignParams(); 1633 // Simplify the schedule according to the context too. 1634 Schedule = Schedule.gist_domain_params(getContext()); 1635 1636 // Predictable parameter order is required for JSON imports. Ensure alignment 1637 // by explicitly calling align_params. 1638 Schedule = Schedule.align_params(Space); 1639 } 1640 1641 static isl::set simplifyAssumptionContext(isl::set AssumptionContext, 1642 const Scop &S) { 1643 // If we have modeled all blocks in the SCoP that have side effects we can 1644 // simplify the context with the constraints that are needed for anything to 1645 // be executed at all. However, if we have error blocks in the SCoP we already 1646 // assumed some parameter combinations cannot occur and removed them from the 1647 // domains, thus we cannot use the remaining domain to simplify the 1648 // assumptions. 1649 if (!S.hasErrorBlock()) { 1650 auto DomainParameters = S.getDomains().params(); 1651 AssumptionContext = AssumptionContext.gist_params(DomainParameters); 1652 } 1653 1654 AssumptionContext = AssumptionContext.gist_params(S.getContext()); 1655 return AssumptionContext; 1656 } 1657 1658 void Scop::simplifyContexts() { 1659 // The parameter constraints of the iteration domains give us a set of 1660 // constraints that need to hold for all cases where at least a single 1661 // statement iteration is executed in the whole scop. We now simplify the 1662 // assumed context under the assumption that such constraints hold and at 1663 // least a single statement iteration is executed. For cases where no 1664 // statement instances are executed, the assumptions we have taken about 1665 // the executed code do not matter and can be changed. 1666 // 1667 // WARNING: This only holds if the assumptions we have taken do not reduce 1668 // the set of statement instances that are executed. Otherwise we 1669 // may run into a case where the iteration domains suggest that 1670 // for a certain set of parameter constraints no code is executed, 1671 // but in the original program some computation would have been 1672 // performed. In such a case, modifying the run-time conditions and 1673 // possibly influencing the run-time check may cause certain scops 1674 // to not be executed. 1675 // 1676 // Example: 1677 // 1678 // When delinearizing the following code: 1679 // 1680 // for (long i = 0; i < 100; i++) 1681 // for (long j = 0; j < m; j++) 1682 // A[i+p][j] = 1.0; 1683 // 1684 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as 1685 // otherwise we would access out of bound data. Now, knowing that code is 1686 // only executed for the case m >= 0, it is sufficient to assume p >= 0. 1687 AssumedContext = simplifyAssumptionContext(AssumedContext, *this); 1688 InvalidContext = InvalidContext.align_params(getParamSpace()); 1689 simplify(DefinedBehaviorContext); 1690 DefinedBehaviorContext = DefinedBehaviorContext.align_params(getParamSpace()); 1691 } 1692 1693 isl::set Scop::getDomainConditions(const ScopStmt *Stmt) const { 1694 return getDomainConditions(Stmt->getEntryBlock()); 1695 } 1696 1697 isl::set Scop::getDomainConditions(BasicBlock *BB) const { 1698 auto DIt = DomainMap.find(BB); 1699 if (DIt != DomainMap.end()) 1700 return DIt->getSecond(); 1701 1702 auto &RI = *R.getRegionInfo(); 1703 auto *BBR = RI.getRegionFor(BB); 1704 while (BBR->getEntry() == BB) 1705 BBR = BBR->getParent(); 1706 return getDomainConditions(BBR->getEntry()); 1707 } 1708 1709 Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI, 1710 DominatorTree &DT, ScopDetection::DetectionContext &DC, 1711 OptimizationRemarkEmitter &ORE, int ID) 1712 : IslCtx(isl_ctx_alloc(), isl_ctx_free), SE(&ScalarEvolution), DT(&DT), 1713 R(R), name(None), HasSingleExitEdge(R.getExitingBlock()), DC(DC), 1714 ORE(ORE), Affinator(this, LI), ID(ID) { 1715 SmallVector<char *, 8> IslArgv; 1716 IslArgv.reserve(1 + IslArgs.size()); 1717 1718 // Substitute for program name. 1719 IslArgv.push_back(const_cast<char *>("-polly-isl-arg")); 1720 1721 for (std::string &Arg : IslArgs) 1722 IslArgv.push_back(const_cast<char *>(Arg.c_str())); 1723 1724 // Abort if unknown argument is passed. 1725 // Note that "-V" (print isl version) will always call exit(0), so we cannot 1726 // avoid ISL aborting the program at this point. 1727 unsigned IslParseFlags = ISL_ARG_ALL; 1728 1729 isl_ctx_parse_options(IslCtx.get(), IslArgv.size(), IslArgv.data(), 1730 IslParseFlags); 1731 1732 if (IslOnErrorAbort) 1733 isl_options_set_on_error(getIslCtx().get(), ISL_ON_ERROR_ABORT); 1734 buildContext(); 1735 } 1736 1737 Scop::~Scop() = default; 1738 1739 void Scop::removeFromStmtMap(ScopStmt &Stmt) { 1740 for (Instruction *Inst : Stmt.getInstructions()) 1741 InstStmtMap.erase(Inst); 1742 1743 if (Stmt.isRegionStmt()) { 1744 for (BasicBlock *BB : Stmt.getRegion()->blocks()) { 1745 StmtMap.erase(BB); 1746 // Skip entry basic block, as its instructions are already deleted as 1747 // part of the statement's instruction list. 1748 if (BB == Stmt.getEntryBlock()) 1749 continue; 1750 for (Instruction &Inst : *BB) 1751 InstStmtMap.erase(&Inst); 1752 } 1753 } else { 1754 auto StmtMapIt = StmtMap.find(Stmt.getBasicBlock()); 1755 if (StmtMapIt != StmtMap.end()) 1756 StmtMapIt->second.erase(std::remove(StmtMapIt->second.begin(), 1757 StmtMapIt->second.end(), &Stmt), 1758 StmtMapIt->second.end()); 1759 for (Instruction *Inst : Stmt.getInstructions()) 1760 InstStmtMap.erase(Inst); 1761 } 1762 } 1763 1764 void Scop::removeStmts(function_ref<bool(ScopStmt &)> ShouldDelete, 1765 bool AfterHoisting) { 1766 for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) { 1767 if (!ShouldDelete(*StmtIt)) { 1768 StmtIt++; 1769 continue; 1770 } 1771 1772 // Start with removing all of the statement's accesses including erasing it 1773 // from all maps that are pointing to them. 1774 // Make a temporary copy because removing MAs invalidates the iterator. 1775 SmallVector<MemoryAccess *, 16> MAList(StmtIt->begin(), StmtIt->end()); 1776 for (MemoryAccess *MA : MAList) 1777 StmtIt->removeSingleMemoryAccess(MA, AfterHoisting); 1778 1779 removeFromStmtMap(*StmtIt); 1780 StmtIt = Stmts.erase(StmtIt); 1781 } 1782 } 1783 1784 void Scop::removeStmtNotInDomainMap() { 1785 removeStmts([this](ScopStmt &Stmt) -> bool { 1786 isl::set Domain = DomainMap.lookup(Stmt.getEntryBlock()); 1787 if (Domain.is_null()) 1788 return true; 1789 return Domain.is_empty(); 1790 }); 1791 } 1792 1793 void Scop::simplifySCoP(bool AfterHoisting) { 1794 removeStmts( 1795 [AfterHoisting](ScopStmt &Stmt) -> bool { 1796 // Never delete statements that contain calls to debug functions. 1797 if (hasDebugCall(&Stmt)) 1798 return false; 1799 1800 bool RemoveStmt = Stmt.isEmpty(); 1801 1802 // Remove read only statements only after invariant load hoisting. 1803 if (!RemoveStmt && AfterHoisting) { 1804 bool OnlyRead = true; 1805 for (MemoryAccess *MA : Stmt) { 1806 if (MA->isRead()) 1807 continue; 1808 1809 OnlyRead = false; 1810 break; 1811 } 1812 1813 RemoveStmt = OnlyRead; 1814 } 1815 return RemoveStmt; 1816 }, 1817 AfterHoisting); 1818 } 1819 1820 InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) { 1821 LoadInst *LInst = dyn_cast<LoadInst>(Val); 1822 if (!LInst) 1823 return nullptr; 1824 1825 if (Value *Rep = InvEquivClassVMap.lookup(LInst)) 1826 LInst = cast<LoadInst>(Rep); 1827 1828 Type *Ty = LInst->getType(); 1829 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); 1830 for (auto &IAClass : InvariantEquivClasses) { 1831 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType) 1832 continue; 1833 1834 auto &MAs = IAClass.InvariantAccesses; 1835 for (auto *MA : MAs) 1836 if (MA->getAccessInstruction() == Val) 1837 return &IAClass; 1838 } 1839 1840 return nullptr; 1841 } 1842 1843 ScopArrayInfo *Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, 1844 ArrayRef<const SCEV *> Sizes, 1845 MemoryKind Kind, 1846 const char *BaseName) { 1847 assert((BasePtr || BaseName) && 1848 "BasePtr and BaseName can not be nullptr at the same time."); 1849 assert(!(BasePtr && BaseName) && "BaseName is redundant."); 1850 auto &SAI = BasePtr ? ScopArrayInfoMap[std::make_pair(BasePtr, Kind)] 1851 : ScopArrayNameMap[BaseName]; 1852 if (!SAI) { 1853 auto &DL = getFunction().getParent()->getDataLayout(); 1854 SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind, 1855 DL, this, BaseName)); 1856 ScopArrayInfoSet.insert(SAI.get()); 1857 } else { 1858 SAI->updateElementType(ElementType); 1859 // In case of mismatching array sizes, we bail out by setting the run-time 1860 // context to false. 1861 if (!SAI->updateSizes(Sizes)) 1862 invalidate(DELINEARIZATION, DebugLoc()); 1863 } 1864 return SAI.get(); 1865 } 1866 1867 ScopArrayInfo *Scop::createScopArrayInfo(Type *ElementType, 1868 const std::string &BaseName, 1869 const std::vector<unsigned> &Sizes) { 1870 auto *DimSizeType = Type::getInt64Ty(getSE()->getContext()); 1871 std::vector<const SCEV *> SCEVSizes; 1872 1873 for (auto size : Sizes) 1874 if (size) 1875 SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false)); 1876 else 1877 SCEVSizes.push_back(nullptr); 1878 1879 auto *SAI = getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes, 1880 MemoryKind::Array, BaseName.c_str()); 1881 return SAI; 1882 } 1883 1884 ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind) { 1885 auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get(); 1886 return SAI; 1887 } 1888 1889 ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) { 1890 auto *SAI = getScopArrayInfoOrNull(BasePtr, Kind); 1891 assert(SAI && "No ScopArrayInfo available for this base pointer"); 1892 return SAI; 1893 } 1894 1895 std::string Scop::getContextStr() const { return getContext().to_str(); } 1896 1897 std::string Scop::getAssumedContextStr() const { 1898 assert(!AssumedContext.is_null() && "Assumed context not yet built"); 1899 return AssumedContext.to_str(); 1900 } 1901 1902 std::string Scop::getInvalidContextStr() const { 1903 return InvalidContext.to_str(); 1904 } 1905 1906 std::string Scop::getNameStr() const { 1907 std::string ExitName, EntryName; 1908 std::tie(EntryName, ExitName) = getEntryExitStr(); 1909 return EntryName + "---" + ExitName; 1910 } 1911 1912 std::pair<std::string, std::string> Scop::getEntryExitStr() const { 1913 std::string ExitName, EntryName; 1914 raw_string_ostream ExitStr(ExitName); 1915 raw_string_ostream EntryStr(EntryName); 1916 1917 R.getEntry()->printAsOperand(EntryStr, false); 1918 EntryStr.str(); 1919 1920 if (R.getExit()) { 1921 R.getExit()->printAsOperand(ExitStr, false); 1922 ExitStr.str(); 1923 } else 1924 ExitName = "FunctionExit"; 1925 1926 return std::make_pair(EntryName, ExitName); 1927 } 1928 1929 isl::set Scop::getContext() const { return Context; } 1930 1931 isl::space Scop::getParamSpace() const { return getContext().get_space(); } 1932 1933 isl::space Scop::getFullParamSpace() const { 1934 std::vector<isl::id> FortranIDs; 1935 FortranIDs = getFortranArrayIds(arrays()); 1936 1937 isl::space Space = isl::space::params_alloc( 1938 getIslCtx(), ParameterIds.size() + FortranIDs.size()); 1939 1940 unsigned PDim = 0; 1941 for (const SCEV *Parameter : Parameters) { 1942 isl::id Id = getIdForParam(Parameter); 1943 Space = Space.set_dim_id(isl::dim::param, PDim++, Id); 1944 } 1945 1946 for (isl::id Id : FortranIDs) 1947 Space = Space.set_dim_id(isl::dim::param, PDim++, Id); 1948 1949 return Space; 1950 } 1951 1952 isl::set Scop::getAssumedContext() const { 1953 assert(!AssumedContext.is_null() && "Assumed context not yet built"); 1954 return AssumedContext; 1955 } 1956 1957 bool Scop::isProfitable(bool ScalarsAreUnprofitable) const { 1958 if (PollyProcessUnprofitable) 1959 return true; 1960 1961 if (isEmpty()) 1962 return false; 1963 1964 unsigned OptimizableStmtsOrLoops = 0; 1965 for (auto &Stmt : *this) { 1966 if (Stmt.getNumIterators() == 0) 1967 continue; 1968 1969 bool ContainsArrayAccs = false; 1970 bool ContainsScalarAccs = false; 1971 for (auto *MA : Stmt) { 1972 if (MA->isRead()) 1973 continue; 1974 ContainsArrayAccs |= MA->isLatestArrayKind(); 1975 ContainsScalarAccs |= MA->isLatestScalarKind(); 1976 } 1977 1978 if (!ScalarsAreUnprofitable || (ContainsArrayAccs && !ContainsScalarAccs)) 1979 OptimizableStmtsOrLoops += Stmt.getNumIterators(); 1980 } 1981 1982 return OptimizableStmtsOrLoops > 1; 1983 } 1984 1985 bool Scop::hasFeasibleRuntimeContext() const { 1986 if (Stmts.empty()) 1987 return false; 1988 1989 isl::set PositiveContext = getAssumedContext(); 1990 isl::set NegativeContext = getInvalidContext(); 1991 PositiveContext = PositiveContext.intersect_params(Context); 1992 PositiveContext = PositiveContext.intersect_params(getDomains().params()); 1993 return PositiveContext.is_empty().is_false() && 1994 PositiveContext.is_subset(NegativeContext).is_false(); 1995 } 1996 1997 MemoryAccess *Scop::lookupBasePtrAccess(MemoryAccess *MA) { 1998 Value *PointerBase = MA->getOriginalBaseAddr(); 1999 2000 auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase); 2001 if (!PointerBaseInst) 2002 return nullptr; 2003 2004 auto *BasePtrStmt = getStmtFor(PointerBaseInst); 2005 if (!BasePtrStmt) 2006 return nullptr; 2007 2008 return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst); 2009 } 2010 2011 static std::string toString(AssumptionKind Kind) { 2012 switch (Kind) { 2013 case ALIASING: 2014 return "No-aliasing"; 2015 case INBOUNDS: 2016 return "Inbounds"; 2017 case WRAPPING: 2018 return "No-overflows"; 2019 case UNSIGNED: 2020 return "Signed-unsigned"; 2021 case COMPLEXITY: 2022 return "Low complexity"; 2023 case PROFITABLE: 2024 return "Profitable"; 2025 case ERRORBLOCK: 2026 return "No-error"; 2027 case INFINITELOOP: 2028 return "Finite loop"; 2029 case INVARIANTLOAD: 2030 return "Invariant load"; 2031 case DELINEARIZATION: 2032 return "Delinearization"; 2033 } 2034 llvm_unreachable("Unknown AssumptionKind!"); 2035 } 2036 2037 bool Scop::isEffectiveAssumption(isl::set Set, AssumptionSign Sign) { 2038 if (Sign == AS_ASSUMPTION) { 2039 if (Context.is_subset(Set)) 2040 return false; 2041 2042 if (AssumedContext.is_subset(Set)) 2043 return false; 2044 } else { 2045 if (Set.is_disjoint(Context)) 2046 return false; 2047 2048 if (Set.is_subset(InvalidContext)) 2049 return false; 2050 } 2051 return true; 2052 } 2053 2054 bool Scop::trackAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, 2055 AssumptionSign Sign, BasicBlock *BB) { 2056 if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign)) 2057 return false; 2058 2059 // Do never emit trivial assumptions as they only clutter the output. 2060 if (!PollyRemarksMinimal) { 2061 isl::set Univ; 2062 if (Sign == AS_ASSUMPTION) 2063 Univ = isl::set::universe(Set.get_space()); 2064 2065 bool IsTrivial = (Sign == AS_RESTRICTION && Set.is_empty()) || 2066 (Sign == AS_ASSUMPTION && Univ.is_equal(Set)); 2067 2068 if (IsTrivial) 2069 return false; 2070 } 2071 2072 switch (Kind) { 2073 case ALIASING: 2074 AssumptionsAliasing++; 2075 break; 2076 case INBOUNDS: 2077 AssumptionsInbounds++; 2078 break; 2079 case WRAPPING: 2080 AssumptionsWrapping++; 2081 break; 2082 case UNSIGNED: 2083 AssumptionsUnsigned++; 2084 break; 2085 case COMPLEXITY: 2086 AssumptionsComplexity++; 2087 break; 2088 case PROFITABLE: 2089 AssumptionsUnprofitable++; 2090 break; 2091 case ERRORBLOCK: 2092 AssumptionsErrorBlock++; 2093 break; 2094 case INFINITELOOP: 2095 AssumptionsInfiniteLoop++; 2096 break; 2097 case INVARIANTLOAD: 2098 AssumptionsInvariantLoad++; 2099 break; 2100 case DELINEARIZATION: 2101 AssumptionsDelinearization++; 2102 break; 2103 } 2104 2105 auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t"; 2106 std::string Msg = toString(Kind) + Suffix + Set.to_str(); 2107 if (BB) 2108 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, BB) 2109 << Msg); 2110 else 2111 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, 2112 R.getEntry()) 2113 << Msg); 2114 return true; 2115 } 2116 2117 void Scop::addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, 2118 AssumptionSign Sign, BasicBlock *BB, 2119 bool RequiresRTC) { 2120 // Simplify the assumptions/restrictions first. 2121 Set = Set.gist_params(getContext()); 2122 intersectDefinedBehavior(Set, Sign); 2123 2124 if (!RequiresRTC) 2125 return; 2126 2127 if (!trackAssumption(Kind, Set, Loc, Sign, BB)) 2128 return; 2129 2130 if (Sign == AS_ASSUMPTION) 2131 AssumedContext = AssumedContext.intersect(Set).coalesce(); 2132 else 2133 InvalidContext = InvalidContext.unite(Set).coalesce(); 2134 } 2135 2136 void Scop::intersectDefinedBehavior(isl::set Set, AssumptionSign Sign) { 2137 if (DefinedBehaviorContext.is_null()) 2138 return; 2139 2140 if (Sign == AS_ASSUMPTION) 2141 DefinedBehaviorContext = DefinedBehaviorContext.intersect(Set); 2142 else 2143 DefinedBehaviorContext = DefinedBehaviorContext.subtract(Set); 2144 2145 // Limit the complexity of the context. If complexity is exceeded, simplify 2146 // the set and check again. 2147 if (DefinedBehaviorContext.n_basic_set() > 2148 MaxDisjunktsInDefinedBehaviourContext) { 2149 simplify(DefinedBehaviorContext); 2150 if (DefinedBehaviorContext.n_basic_set() > 2151 MaxDisjunktsInDefinedBehaviourContext) 2152 DefinedBehaviorContext = {}; 2153 } 2154 } 2155 2156 void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) { 2157 LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n"); 2158 addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB); 2159 } 2160 2161 isl::set Scop::getInvalidContext() const { return InvalidContext; } 2162 2163 void Scop::printContext(raw_ostream &OS) const { 2164 OS << "Context:\n"; 2165 OS.indent(4) << Context << "\n"; 2166 2167 OS.indent(4) << "Assumed Context:\n"; 2168 OS.indent(4) << AssumedContext << "\n"; 2169 2170 OS.indent(4) << "Invalid Context:\n"; 2171 OS.indent(4) << InvalidContext << "\n"; 2172 2173 OS.indent(4) << "Defined Behavior Context:\n"; 2174 if (!DefinedBehaviorContext.is_null()) 2175 OS.indent(4) << DefinedBehaviorContext << "\n"; 2176 else 2177 OS.indent(4) << "<unavailable>\n"; 2178 2179 unsigned Dim = 0; 2180 for (const SCEV *Parameter : Parameters) 2181 OS.indent(4) << "p" << Dim++ << ": " << *Parameter << "\n"; 2182 } 2183 2184 void Scop::printAliasAssumptions(raw_ostream &OS) const { 2185 int noOfGroups = 0; 2186 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 2187 if (Pair.second.size() == 0) 2188 noOfGroups += 1; 2189 else 2190 noOfGroups += Pair.second.size(); 2191 } 2192 2193 OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n"; 2194 if (MinMaxAliasGroups.empty()) { 2195 OS.indent(8) << "n/a\n"; 2196 return; 2197 } 2198 2199 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) { 2200 2201 // If the group has no read only accesses print the write accesses. 2202 if (Pair.second.empty()) { 2203 OS.indent(8) << "[["; 2204 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 2205 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 2206 << ">"; 2207 } 2208 OS << " ]]\n"; 2209 } 2210 2211 for (const MinMaxAccessTy &MMAReadOnly : Pair.second) { 2212 OS.indent(8) << "[["; 2213 OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">"; 2214 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) { 2215 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second 2216 << ">"; 2217 } 2218 OS << " ]]\n"; 2219 } 2220 } 2221 } 2222 2223 void Scop::printStatements(raw_ostream &OS, bool PrintInstructions) const { 2224 OS << "Statements {\n"; 2225 2226 for (const ScopStmt &Stmt : *this) { 2227 OS.indent(4); 2228 Stmt.print(OS, PrintInstructions); 2229 } 2230 2231 OS.indent(4) << "}\n"; 2232 } 2233 2234 void Scop::printArrayInfo(raw_ostream &OS) const { 2235 OS << "Arrays {\n"; 2236 2237 for (auto &Array : arrays()) 2238 Array->print(OS); 2239 2240 OS.indent(4) << "}\n"; 2241 2242 OS.indent(4) << "Arrays (Bounds as pw_affs) {\n"; 2243 2244 for (auto &Array : arrays()) 2245 Array->print(OS, /* SizeAsPwAff */ true); 2246 2247 OS.indent(4) << "}\n"; 2248 } 2249 2250 void Scop::print(raw_ostream &OS, bool PrintInstructions) const { 2251 OS.indent(4) << "Function: " << getFunction().getName() << "\n"; 2252 OS.indent(4) << "Region: " << getNameStr() << "\n"; 2253 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; 2254 OS.indent(4) << "Invariant Accesses: {\n"; 2255 for (const auto &IAClass : InvariantEquivClasses) { 2256 const auto &MAs = IAClass.InvariantAccesses; 2257 if (MAs.empty()) { 2258 OS.indent(12) << "Class Pointer: " << *IAClass.IdentifyingPointer << "\n"; 2259 } else { 2260 MAs.front()->print(OS); 2261 OS.indent(12) << "Execution Context: " << IAClass.ExecutionContext 2262 << "\n"; 2263 } 2264 } 2265 OS.indent(4) << "}\n"; 2266 printContext(OS.indent(4)); 2267 printArrayInfo(OS.indent(4)); 2268 printAliasAssumptions(OS); 2269 printStatements(OS.indent(4), PrintInstructions); 2270 } 2271 2272 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 2273 LLVM_DUMP_METHOD void Scop::dump() const { print(dbgs(), true); } 2274 #endif 2275 2276 isl::ctx Scop::getIslCtx() const { return IslCtx.get(); } 2277 2278 __isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB, 2279 bool NonNegative, 2280 RecordedAssumptionsTy *RecordedAssumptions) { 2281 // First try to use the SCEVAffinator to generate a piecewise defined 2282 // affine function from @p E in the context of @p BB. If that tasks becomes to 2283 // complex the affinator might return a nullptr. In such a case we invalidate 2284 // the SCoP and return a dummy value. This way we do not need to add error 2285 // handling code to all users of this function. 2286 auto PWAC = Affinator.getPwAff(E, BB, RecordedAssumptions); 2287 if (!PWAC.first.is_null()) { 2288 // TODO: We could use a heuristic and either use: 2289 // SCEVAffinator::takeNonNegativeAssumption 2290 // or 2291 // SCEVAffinator::interpretAsUnsigned 2292 // to deal with unsigned or "NonNegative" SCEVs. 2293 if (NonNegative) 2294 Affinator.takeNonNegativeAssumption(PWAC, RecordedAssumptions); 2295 return PWAC; 2296 } 2297 2298 auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc(); 2299 invalidate(COMPLEXITY, DL, BB); 2300 return Affinator.getPwAff(SE->getZero(E->getType()), BB, RecordedAssumptions); 2301 } 2302 2303 isl::union_set Scop::getDomains() const { 2304 isl_space *EmptySpace = isl_space_params_alloc(getIslCtx().get(), 0); 2305 isl_union_set *Domain = isl_union_set_empty(EmptySpace); 2306 2307 for (const ScopStmt &Stmt : *this) 2308 Domain = isl_union_set_add_set(Domain, Stmt.getDomain().release()); 2309 2310 return isl::manage(Domain); 2311 } 2312 2313 isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB, 2314 RecordedAssumptionsTy *RecordedAssumptions) { 2315 PWACtx PWAC = getPwAff(E, BB, RecordedAssumptions); 2316 return PWAC.first; 2317 } 2318 2319 isl::union_map 2320 Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) { 2321 isl::union_map Accesses = isl::union_map::empty(getParamSpace()); 2322 2323 for (ScopStmt &Stmt : *this) { 2324 for (MemoryAccess *MA : Stmt) { 2325 if (!Predicate(*MA)) 2326 continue; 2327 2328 isl::set Domain = Stmt.getDomain(); 2329 isl::map AccessDomain = MA->getAccessRelation(); 2330 AccessDomain = AccessDomain.intersect_domain(Domain); 2331 Accesses = Accesses.add_map(AccessDomain); 2332 } 2333 } 2334 2335 return Accesses.coalesce(); 2336 } 2337 2338 isl::union_map Scop::getMustWrites() { 2339 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); }); 2340 } 2341 2342 isl::union_map Scop::getMayWrites() { 2343 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); }); 2344 } 2345 2346 isl::union_map Scop::getWrites() { 2347 return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); }); 2348 } 2349 2350 isl::union_map Scop::getReads() { 2351 return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); }); 2352 } 2353 2354 isl::union_map Scop::getAccesses() { 2355 return getAccessesOfType([](MemoryAccess &MA) { return true; }); 2356 } 2357 2358 isl::union_map Scop::getAccesses(ScopArrayInfo *Array) { 2359 return getAccessesOfType( 2360 [Array](MemoryAccess &MA) { return MA.getScopArrayInfo() == Array; }); 2361 } 2362 2363 isl::union_map Scop::getSchedule() const { 2364 auto Tree = getScheduleTree(); 2365 return Tree.get_map(); 2366 } 2367 2368 isl::schedule Scop::getScheduleTree() const { 2369 return Schedule.intersect_domain(getDomains()); 2370 } 2371 2372 void Scop::setSchedule(isl::union_map NewSchedule) { 2373 auto S = isl::schedule::from_domain(getDomains()); 2374 Schedule = S.insert_partial_schedule( 2375 isl::multi_union_pw_aff::from_union_map(NewSchedule)); 2376 ScheduleModified = true; 2377 } 2378 2379 void Scop::setScheduleTree(isl::schedule NewSchedule) { 2380 Schedule = NewSchedule; 2381 ScheduleModified = true; 2382 } 2383 2384 bool Scop::restrictDomains(isl::union_set Domain) { 2385 bool Changed = false; 2386 for (ScopStmt &Stmt : *this) { 2387 isl::union_set StmtDomain = isl::union_set(Stmt.getDomain()); 2388 isl::union_set NewStmtDomain = StmtDomain.intersect(Domain); 2389 2390 if (StmtDomain.is_subset(NewStmtDomain)) 2391 continue; 2392 2393 Changed = true; 2394 2395 NewStmtDomain = NewStmtDomain.coalesce(); 2396 2397 if (NewStmtDomain.is_empty()) 2398 Stmt.restrictDomain(isl::set::empty(Stmt.getDomainSpace())); 2399 else 2400 Stmt.restrictDomain(isl::set(NewStmtDomain)); 2401 } 2402 return Changed; 2403 } 2404 2405 ScalarEvolution *Scop::getSE() const { return SE; } 2406 2407 void Scop::addScopStmt(BasicBlock *BB, StringRef Name, Loop *SurroundingLoop, 2408 std::vector<Instruction *> Instructions) { 2409 assert(BB && "Unexpected nullptr!"); 2410 Stmts.emplace_back(*this, *BB, Name, SurroundingLoop, Instructions); 2411 auto *Stmt = &Stmts.back(); 2412 StmtMap[BB].push_back(Stmt); 2413 for (Instruction *Inst : Instructions) { 2414 assert(!InstStmtMap.count(Inst) && 2415 "Unexpected statement corresponding to the instruction."); 2416 InstStmtMap[Inst] = Stmt; 2417 } 2418 } 2419 2420 void Scop::addScopStmt(Region *R, StringRef Name, Loop *SurroundingLoop, 2421 std::vector<Instruction *> Instructions) { 2422 assert(R && "Unexpected nullptr!"); 2423 Stmts.emplace_back(*this, *R, Name, SurroundingLoop, Instructions); 2424 auto *Stmt = &Stmts.back(); 2425 2426 for (Instruction *Inst : Instructions) { 2427 assert(!InstStmtMap.count(Inst) && 2428 "Unexpected statement corresponding to the instruction."); 2429 InstStmtMap[Inst] = Stmt; 2430 } 2431 2432 for (BasicBlock *BB : R->blocks()) { 2433 StmtMap[BB].push_back(Stmt); 2434 if (BB == R->getEntry()) 2435 continue; 2436 for (Instruction &Inst : *BB) { 2437 assert(!InstStmtMap.count(&Inst) && 2438 "Unexpected statement corresponding to the instruction."); 2439 InstStmtMap[&Inst] = Stmt; 2440 } 2441 } 2442 } 2443 2444 ScopStmt *Scop::addScopStmt(isl::map SourceRel, isl::map TargetRel, 2445 isl::set Domain) { 2446 #ifndef NDEBUG 2447 isl::set SourceDomain = SourceRel.domain(); 2448 isl::set TargetDomain = TargetRel.domain(); 2449 assert(Domain.is_subset(TargetDomain) && 2450 "Target access not defined for complete statement domain"); 2451 assert(Domain.is_subset(SourceDomain) && 2452 "Source access not defined for complete statement domain"); 2453 #endif 2454 Stmts.emplace_back(*this, SourceRel, TargetRel, Domain); 2455 CopyStmtsNum++; 2456 return &(Stmts.back()); 2457 } 2458 2459 ArrayRef<ScopStmt *> Scop::getStmtListFor(BasicBlock *BB) const { 2460 auto StmtMapIt = StmtMap.find(BB); 2461 if (StmtMapIt == StmtMap.end()) 2462 return {}; 2463 return StmtMapIt->second; 2464 } 2465 2466 ScopStmt *Scop::getIncomingStmtFor(const Use &U) const { 2467 auto *PHI = cast<PHINode>(U.getUser()); 2468 BasicBlock *IncomingBB = PHI->getIncomingBlock(U); 2469 2470 // If the value is a non-synthesizable from the incoming block, use the 2471 // statement that contains it as user statement. 2472 if (auto *IncomingInst = dyn_cast<Instruction>(U.get())) { 2473 if (IncomingInst->getParent() == IncomingBB) { 2474 if (ScopStmt *IncomingStmt = getStmtFor(IncomingInst)) 2475 return IncomingStmt; 2476 } 2477 } 2478 2479 // Otherwise, use the epilogue/last statement. 2480 return getLastStmtFor(IncomingBB); 2481 } 2482 2483 ScopStmt *Scop::getLastStmtFor(BasicBlock *BB) const { 2484 ArrayRef<ScopStmt *> StmtList = getStmtListFor(BB); 2485 if (!StmtList.empty()) 2486 return StmtList.back(); 2487 return nullptr; 2488 } 2489 2490 ArrayRef<ScopStmt *> Scop::getStmtListFor(RegionNode *RN) const { 2491 if (RN->isSubRegion()) 2492 return getStmtListFor(RN->getNodeAs<Region>()); 2493 return getStmtListFor(RN->getNodeAs<BasicBlock>()); 2494 } 2495 2496 ArrayRef<ScopStmt *> Scop::getStmtListFor(Region *R) const { 2497 return getStmtListFor(R->getEntry()); 2498 } 2499 2500 int Scop::getRelativeLoopDepth(const Loop *L) const { 2501 if (!L || !R.contains(L)) 2502 return -1; 2503 // outermostLoopInRegion always returns nullptr for top level regions 2504 if (R.isTopLevelRegion()) { 2505 // LoopInfo's depths start at 1, we start at 0 2506 return L->getLoopDepth() - 1; 2507 } else { 2508 Loop *OuterLoop = R.outermostLoopInRegion(const_cast<Loop *>(L)); 2509 assert(OuterLoop); 2510 return L->getLoopDepth() - OuterLoop->getLoopDepth(); 2511 } 2512 } 2513 2514 ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) { 2515 for (auto &SAI : arrays()) { 2516 if (SAI->getName() == BaseName) 2517 return SAI; 2518 } 2519 return nullptr; 2520 } 2521 2522 void Scop::addAccessData(MemoryAccess *Access) { 2523 const ScopArrayInfo *SAI = Access->getOriginalScopArrayInfo(); 2524 assert(SAI && "can only use after access relations have been constructed"); 2525 2526 if (Access->isOriginalValueKind() && Access->isRead()) 2527 ValueUseAccs[SAI].push_back(Access); 2528 else if (Access->isOriginalAnyPHIKind() && Access->isWrite()) 2529 PHIIncomingAccs[SAI].push_back(Access); 2530 } 2531 2532 void Scop::removeAccessData(MemoryAccess *Access) { 2533 if (Access->isOriginalValueKind() && Access->isWrite()) { 2534 ValueDefAccs.erase(Access->getAccessValue()); 2535 } else if (Access->isOriginalValueKind() && Access->isRead()) { 2536 auto &Uses = ValueUseAccs[Access->getScopArrayInfo()]; 2537 auto NewEnd = std::remove(Uses.begin(), Uses.end(), Access); 2538 Uses.erase(NewEnd, Uses.end()); 2539 } else if (Access->isOriginalPHIKind() && Access->isRead()) { 2540 PHINode *PHI = cast<PHINode>(Access->getAccessInstruction()); 2541 PHIReadAccs.erase(PHI); 2542 } else if (Access->isOriginalAnyPHIKind() && Access->isWrite()) { 2543 auto &Incomings = PHIIncomingAccs[Access->getScopArrayInfo()]; 2544 auto NewEnd = std::remove(Incomings.begin(), Incomings.end(), Access); 2545 Incomings.erase(NewEnd, Incomings.end()); 2546 } 2547 } 2548 2549 MemoryAccess *Scop::getValueDef(const ScopArrayInfo *SAI) const { 2550 assert(SAI->isValueKind()); 2551 2552 Instruction *Val = dyn_cast<Instruction>(SAI->getBasePtr()); 2553 if (!Val) 2554 return nullptr; 2555 2556 return ValueDefAccs.lookup(Val); 2557 } 2558 2559 ArrayRef<MemoryAccess *> Scop::getValueUses(const ScopArrayInfo *SAI) const { 2560 assert(SAI->isValueKind()); 2561 auto It = ValueUseAccs.find(SAI); 2562 if (It == ValueUseAccs.end()) 2563 return {}; 2564 return It->second; 2565 } 2566 2567 MemoryAccess *Scop::getPHIRead(const ScopArrayInfo *SAI) const { 2568 assert(SAI->isPHIKind() || SAI->isExitPHIKind()); 2569 2570 if (SAI->isExitPHIKind()) 2571 return nullptr; 2572 2573 PHINode *PHI = cast<PHINode>(SAI->getBasePtr()); 2574 return PHIReadAccs.lookup(PHI); 2575 } 2576 2577 ArrayRef<MemoryAccess *> Scop::getPHIIncomings(const ScopArrayInfo *SAI) const { 2578 assert(SAI->isPHIKind() || SAI->isExitPHIKind()); 2579 auto It = PHIIncomingAccs.find(SAI); 2580 if (It == PHIIncomingAccs.end()) 2581 return {}; 2582 return It->second; 2583 } 2584 2585 bool Scop::isEscaping(Instruction *Inst) { 2586 assert(contains(Inst) && "The concept of escaping makes only sense for " 2587 "values defined inside the SCoP"); 2588 2589 for (Use &Use : Inst->uses()) { 2590 BasicBlock *UserBB = getUseBlock(Use); 2591 if (!contains(UserBB)) 2592 return true; 2593 2594 // When the SCoP region exit needs to be simplified, PHIs in the region exit 2595 // move to a new basic block such that its incoming blocks are not in the 2596 // SCoP anymore. 2597 if (hasSingleExitEdge() && isa<PHINode>(Use.getUser()) && 2598 isExit(cast<PHINode>(Use.getUser())->getParent())) 2599 return true; 2600 } 2601 return false; 2602 } 2603 2604 void Scop::incrementNumberOfAliasingAssumptions(unsigned step) { 2605 AssumptionsAliasing += step; 2606 } 2607 2608 Scop::ScopStatistics Scop::getStatistics() const { 2609 ScopStatistics Result; 2610 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 2611 auto LoopStat = ScopDetection::countBeneficialLoops(&R, *SE, *getLI(), 0); 2612 2613 int NumTotalLoops = LoopStat.NumLoops; 2614 Result.NumBoxedLoops = getBoxedLoops().size(); 2615 Result.NumAffineLoops = NumTotalLoops - Result.NumBoxedLoops; 2616 2617 for (const ScopStmt &Stmt : *this) { 2618 isl::set Domain = Stmt.getDomain().intersect_params(getContext()); 2619 bool IsInLoop = Stmt.getNumIterators() >= 1; 2620 for (MemoryAccess *MA : Stmt) { 2621 if (!MA->isWrite()) 2622 continue; 2623 2624 if (MA->isLatestValueKind()) { 2625 Result.NumValueWrites += 1; 2626 if (IsInLoop) 2627 Result.NumValueWritesInLoops += 1; 2628 } 2629 2630 if (MA->isLatestAnyPHIKind()) { 2631 Result.NumPHIWrites += 1; 2632 if (IsInLoop) 2633 Result.NumPHIWritesInLoops += 1; 2634 } 2635 2636 isl::set AccSet = 2637 MA->getAccessRelation().intersect_domain(Domain).range(); 2638 if (AccSet.is_singleton()) { 2639 Result.NumSingletonWrites += 1; 2640 if (IsInLoop) 2641 Result.NumSingletonWritesInLoops += 1; 2642 } 2643 } 2644 } 2645 #endif 2646 return Result; 2647 } 2648 2649 raw_ostream &polly::operator<<(raw_ostream &OS, const Scop &scop) { 2650 scop.print(OS, PollyPrintInstructions); 2651 return OS; 2652 } 2653 2654 //===----------------------------------------------------------------------===// 2655 void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const { 2656 AU.addRequired<LoopInfoWrapperPass>(); 2657 AU.addRequired<RegionInfoPass>(); 2658 AU.addRequired<DominatorTreeWrapperPass>(); 2659 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 2660 AU.addRequiredTransitive<ScopDetectionWrapperPass>(); 2661 AU.addRequired<AAResultsWrapperPass>(); 2662 AU.addRequired<AssumptionCacheTracker>(); 2663 AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); 2664 AU.setPreservesAll(); 2665 } 2666 2667 void updateLoopCountStatistic(ScopDetection::LoopStats Stats, 2668 Scop::ScopStatistics ScopStats) { 2669 assert(Stats.NumLoops == ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops); 2670 2671 NumScops++; 2672 NumLoopsInScop += Stats.NumLoops; 2673 MaxNumLoopsInScop = 2674 std::max(MaxNumLoopsInScop.getValue(), (unsigned)Stats.NumLoops); 2675 2676 if (Stats.MaxDepth == 0) 2677 NumScopsDepthZero++; 2678 else if (Stats.MaxDepth == 1) 2679 NumScopsDepthOne++; 2680 else if (Stats.MaxDepth == 2) 2681 NumScopsDepthTwo++; 2682 else if (Stats.MaxDepth == 3) 2683 NumScopsDepthThree++; 2684 else if (Stats.MaxDepth == 4) 2685 NumScopsDepthFour++; 2686 else if (Stats.MaxDepth == 5) 2687 NumScopsDepthFive++; 2688 else 2689 NumScopsDepthLarger++; 2690 2691 NumAffineLoops += ScopStats.NumAffineLoops; 2692 NumBoxedLoops += ScopStats.NumBoxedLoops; 2693 2694 NumValueWrites += ScopStats.NumValueWrites; 2695 NumValueWritesInLoops += ScopStats.NumValueWritesInLoops; 2696 NumPHIWrites += ScopStats.NumPHIWrites; 2697 NumPHIWritesInLoops += ScopStats.NumPHIWritesInLoops; 2698 NumSingletonWrites += ScopStats.NumSingletonWrites; 2699 NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops; 2700 } 2701 2702 bool ScopInfoRegionPass::runOnRegion(Region *R, RGPassManager &RGM) { 2703 auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD(); 2704 2705 if (!SD.isMaxRegionInScop(*R)) 2706 return false; 2707 2708 Function *F = R->getEntry()->getParent(); 2709 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 2710 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 2711 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); 2712 auto const &DL = F->getParent()->getDataLayout(); 2713 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 2714 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F); 2715 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); 2716 2717 ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE); 2718 S = SB.getScop(); // take ownership of scop object 2719 2720 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 2721 if (S) { 2722 ScopDetection::LoopStats Stats = 2723 ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0); 2724 updateLoopCountStatistic(Stats, S->getStatistics()); 2725 } 2726 #endif 2727 2728 return false; 2729 } 2730 2731 void ScopInfoRegionPass::print(raw_ostream &OS, const Module *) const { 2732 if (S) 2733 S->print(OS, PollyPrintInstructions); 2734 else 2735 OS << "Invalid Scop!\n"; 2736 } 2737 2738 char ScopInfoRegionPass::ID = 0; 2739 2740 Pass *polly::createScopInfoRegionPassPass() { return new ScopInfoRegionPass(); } 2741 2742 INITIALIZE_PASS_BEGIN(ScopInfoRegionPass, "polly-scops", 2743 "Polly - Create polyhedral description of Scops", false, 2744 false); 2745 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); 2746 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); 2747 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 2748 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 2749 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 2750 INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); 2751 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 2752 INITIALIZE_PASS_END(ScopInfoRegionPass, "polly-scops", 2753 "Polly - Create polyhedral description of Scops", false, 2754 false) 2755 2756 //===----------------------------------------------------------------------===// 2757 ScopInfo::ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE, 2758 LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT, 2759 AssumptionCache &AC, OptimizationRemarkEmitter &ORE) 2760 : DL(DL), SD(SD), SE(SE), LI(LI), AA(AA), DT(DT), AC(AC), ORE(ORE) { 2761 recompute(); 2762 } 2763 2764 void ScopInfo::recompute() { 2765 RegionToScopMap.clear(); 2766 /// Create polyhedral description of scops for all the valid regions of a 2767 /// function. 2768 for (auto &It : SD) { 2769 Region *R = const_cast<Region *>(It); 2770 if (!SD.isMaxRegionInScop(*R)) 2771 continue; 2772 2773 ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE); 2774 std::unique_ptr<Scop> S = SB.getScop(); 2775 if (!S) 2776 continue; 2777 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 2778 ScopDetection::LoopStats Stats = 2779 ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0); 2780 updateLoopCountStatistic(Stats, S->getStatistics()); 2781 #endif 2782 bool Inserted = RegionToScopMap.insert({R, std::move(S)}).second; 2783 assert(Inserted && "Building Scop for the same region twice!"); 2784 (void)Inserted; 2785 } 2786 } 2787 2788 bool ScopInfo::invalidate(Function &F, const PreservedAnalyses &PA, 2789 FunctionAnalysisManager::Invalidator &Inv) { 2790 // Check whether the analysis, all analyses on functions have been preserved 2791 // or anything we're holding references to is being invalidated 2792 auto PAC = PA.getChecker<ScopInfoAnalysis>(); 2793 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) || 2794 Inv.invalidate<ScopAnalysis>(F, PA) || 2795 Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) || 2796 Inv.invalidate<LoopAnalysis>(F, PA) || 2797 Inv.invalidate<AAManager>(F, PA) || 2798 Inv.invalidate<DominatorTreeAnalysis>(F, PA) || 2799 Inv.invalidate<AssumptionAnalysis>(F, PA); 2800 } 2801 2802 AnalysisKey ScopInfoAnalysis::Key; 2803 2804 ScopInfoAnalysis::Result ScopInfoAnalysis::run(Function &F, 2805 FunctionAnalysisManager &FAM) { 2806 auto &SD = FAM.getResult<ScopAnalysis>(F); 2807 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F); 2808 auto &LI = FAM.getResult<LoopAnalysis>(F); 2809 auto &AA = FAM.getResult<AAManager>(F); 2810 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); 2811 auto &AC = FAM.getResult<AssumptionAnalysis>(F); 2812 auto &DL = F.getParent()->getDataLayout(); 2813 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F); 2814 return {DL, SD, SE, LI, AA, DT, AC, ORE}; 2815 } 2816 2817 PreservedAnalyses ScopInfoPrinterPass::run(Function &F, 2818 FunctionAnalysisManager &FAM) { 2819 auto &SI = FAM.getResult<ScopInfoAnalysis>(F); 2820 // Since the legacy PM processes Scops in bottom up, we print them in reverse 2821 // order here to keep the output persistent 2822 for (auto &It : reverse(SI)) { 2823 if (It.second) 2824 It.second->print(Stream, PollyPrintInstructions); 2825 else 2826 Stream << "Invalid Scop!\n"; 2827 } 2828 return PreservedAnalyses::all(); 2829 } 2830 2831 void ScopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 2832 AU.addRequired<LoopInfoWrapperPass>(); 2833 AU.addRequired<RegionInfoPass>(); 2834 AU.addRequired<DominatorTreeWrapperPass>(); 2835 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); 2836 AU.addRequiredTransitive<ScopDetectionWrapperPass>(); 2837 AU.addRequired<AAResultsWrapperPass>(); 2838 AU.addRequired<AssumptionCacheTracker>(); 2839 AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); 2840 AU.setPreservesAll(); 2841 } 2842 2843 bool ScopInfoWrapperPass::runOnFunction(Function &F) { 2844 auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD(); 2845 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 2846 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 2847 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); 2848 auto const &DL = F.getParent()->getDataLayout(); 2849 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 2850 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 2851 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); 2852 2853 Result.reset(new ScopInfo{DL, SD, SE, LI, AA, DT, AC, ORE}); 2854 return false; 2855 } 2856 2857 void ScopInfoWrapperPass::print(raw_ostream &OS, const Module *) const { 2858 for (auto &It : *Result) { 2859 if (It.second) 2860 It.second->print(OS, PollyPrintInstructions); 2861 else 2862 OS << "Invalid Scop!\n"; 2863 } 2864 } 2865 2866 char ScopInfoWrapperPass::ID = 0; 2867 2868 Pass *polly::createScopInfoWrapperPassPass() { 2869 return new ScopInfoWrapperPass(); 2870 } 2871 2872 INITIALIZE_PASS_BEGIN( 2873 ScopInfoWrapperPass, "polly-function-scops", 2874 "Polly - Create polyhedral description of all Scops of a function", false, 2875 false); 2876 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); 2877 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); 2878 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 2879 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 2880 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 2881 INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); 2882 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 2883 INITIALIZE_PASS_END( 2884 ScopInfoWrapperPass, "polly-function-scops", 2885 "Polly - Create polyhedral description of all Scops of a function", false, 2886 false) 2887