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