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