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