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