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