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