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