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