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