25#include "llvm/ADT/ArrayRef.h"
26#include "llvm/ADT/EquivalenceClasses.h"
27#include "llvm/ADT/PostOrderIterator.h"
28#include "llvm/ADT/Sequence.h"
29#include "llvm/ADT/SmallSet.h"
30#include "llvm/ADT/Statistic.h"
31#include "llvm/Analysis/AliasAnalysis.h"
32#include "llvm/Analysis/AssumptionCache.h"
33#include "llvm/Analysis/Delinearization.h"
34#include "llvm/Analysis/Loads.h"
35#include "llvm/Analysis/LoopInfo.h"
36#include "llvm/Analysis/OptimizationRemarkEmitter.h"
37#include "llvm/Analysis/RegionInfo.h"
38#include "llvm/Analysis/RegionIterator.h"
39#include "llvm/Analysis/ScalarEvolution.h"
40#include "llvm/Analysis/ScalarEvolutionExpressions.h"
41#include "llvm/IR/BasicBlock.h"
42#include "llvm/IR/DataLayout.h"
43#include "llvm/IR/DebugLoc.h"
44#include "llvm/IR/DerivedTypes.h"
45#include "llvm/IR/Dominators.h"
46#include "llvm/IR/Function.h"
47#include "llvm/IR/InstrTypes.h"
48#include "llvm/IR/Instruction.h"
49#include "llvm/IR/Instructions.h"
50#include "llvm/IR/Type.h"
51#include "llvm/IR/Use.h"
52#include "llvm/IR/Value.h"
53#include "llvm/Support/CommandLine.h"
54#include "llvm/Support/Compiler.h"
55#include "llvm/Support/Debug.h"
56#include "llvm/Support/ErrorHandling.h"
57#include "llvm/Support/raw_ostream.h"
65#define DEBUG_TYPE "polly-scops"
68STATISTIC(RichScopFound,
"Number of Scops containing a loop");
70 "Number of SCoPs with statically infeasible context.");
81 "polly-analyze-read-only-scalars",
82 cl::desc(
"Model read-only scalar values in the scop description"),
88 cl::desc(
"Bound the scop analysis by a maximal amount of "
89 "computational steps (0 means no bound)"),
93 "polly-allow-dereference-of-all-function-parameters",
95 "Treat all parameters to functions that are pointers as dereferencible."
96 " This is useful for invariant load hoisting, since we can generate"
97 " less runtime checks. This is only valid if all pointers to functions"
98 " are always initialized, so that Polly can choose to hoist"
104 cl::desc(
"Do not take inbounds assumptions at all"),
108 "polly-rtc-max-arrays-per-group",
109 cl::desc(
"The maximal number of arrays to compare in each alias group."),
113 "polly-rtc-max-array-disjuncts",
114 cl::desc(
"The maximal number of disjunts allowed in memory accesses to "
119 "polly-rtc-max-parameters",
120 cl::desc(
"The maximal number of parameters allowed in RTCs."), cl::Hidden,
124 "polly-unprofitable-scalar-accs",
125 cl::desc(
"Count statements with scalar accesses as not optimizable"),
129 "polly-context", cl::value_desc(
"isl parameter set"),
130 cl::desc(
"Provide additional constraints on the context parameters"),
134 cl::desc(
"Detect and exploit reductions"),
135 cl::Hidden, cl::init(
true),
142 "polly-disable-multiplicative-reductions",
143 cl::desc(
"Disable multiplicative reductions"), cl::Hidden,
149 "polly-stmt-granularity",
151 "Algorithm to use for splitting basic blocks into multiple statements"),
153 "One statement per basic block"),
155 "Scalar independence heuristic"),
157 "Store-level granularity")),
166 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry()
167 : RN->getNodeAs<BasicBlock>();
171static inline BasicBlock *
173 if (RN->isSubRegion()) {
175 return RN->getNodeAs<Region>()->getExit();
177 return TI->getSuccessor(idx);
182 if (!RN->isSubRegion())
183 return SD->
isErrorBlock(*RN->getNodeAs<BasicBlock>(), R);
184 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks())
208 C =
C.set_constant_si(1);
211 NextIterationMap = NextIterationMap.add_constraint(
C);
212 return NextIterationMap;
219 if (BSet.is_bounded())
237 assert(NumDimsS >= Dim + 1);
238 OnlyDimS = OnlyDimS.project_out(
isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
244 for (
unsigned u = 0; u < Dim; u++) {
249 OnlyDimS = OnlyDimS.add_constraint(
C);
257 BoundedParts.insert_dims(
isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
262 isl::set UnboundedParts =
S.subtract(BoundedParts);
263 return std::make_pair(UnboundedParts, BoundedParts);
270 case ICmpInst::ICMP_EQ:
272 case ICmpInst::ICMP_NE:
274 case ICmpInst::ICMP_SLT:
276 case ICmpInst::ICMP_SLE:
278 case ICmpInst::ICMP_SGT:
280 case ICmpInst::ICMP_SGE:
282 case ICmpInst::ICMP_ULT:
284 case ICmpInst::ICMP_UGT:
286 case ICmpInst::ICMP_ULE:
288 case ICmpInst::ICMP_UGE:
291 llvm_unreachable(
"Non integer predicate not supported");
301 int OldDepth =
scop->getRelativeLoopDepth(OldL);
302 int NewDepth =
scop->getRelativeLoopDepth(NewL);
304 if (OldDepth == -1 && NewDepth == -1)
314 if (OldDepth == NewDepth) {
315 assert(OldL->getParentLoop() == NewL->getParentLoop());
318 }
else if (OldDepth < NewDepth) {
319 assert(OldDepth + 1 == NewDepth);
320 auto &R =
scop->getRegion();
322 assert(NewL->getParentLoop() == OldL ||
323 ((!OldL || !R.contains(OldL)) && R.contains(NewL)));
326 assert(OldDepth > NewDepth);
327 unsigned Diff = OldDepth - NewDepth;
338 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
339 const SCEV *E,
bool NonNegative,
bool IsInsideDomain) {
342 InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second);
343 return std::move(PWAC.first);
356 const SCEV *SCEV_TestVal,
const SCEV *SCEV_UpperBound,
357 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
bool IsStrictUpperBound,
358 bool IsInsideDomain) {
362 false, IsInsideDomain);
365 true, IsInsideDomain);
372 if (IsStrictUpperBound)
374 Second = TestVal.
lt_set(std::move(UpperBound));
377 Second = TestVal.
le_set(std::move(UpperBound));
380 return ConsequenceCondSet;
385 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
386 SmallVectorImpl<__isl_give isl_set *> &ConditionSets,
bool IsInsideDomain) {
387 Value *Condition = SI->getCondition();
390 LHS =
getPwAff(BB, InvalidDomainMap,
SE.getSCEVAtScope(Condition, L),
391 false, IsInsideDomain)
394 unsigned NumSuccessors = SI->getNumSuccessors();
395 ConditionSets.resize(NumSuccessors);
396 for (
auto &Case : SI->cases()) {
397 unsigned Idx = Case.getSuccessorIndex();
398 ConstantInt *CaseValue = Case.getCaseValue();
400 RHS =
getPwAff(BB, InvalidDomainMap,
SE.getSCEV(CaseValue),
401 false, IsInsideDomain)
411 assert(ConditionSets[0] ==
nullptr &&
"Default condition set was set");
413 for (
unsigned u = 2; u < NumSuccessors; u++)
424 BasicBlock *BB,
Value *Condition, Instruction *TI, Loop *L,
426 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
427 SmallVectorImpl<__isl_give isl_set *> &ConditionSets,
bool IsInsideDomain) {
428 isl_set *ConsequenceCondSet =
nullptr;
430 if (
auto Load = dyn_cast<LoadInst>(Condition)) {
431 const SCEV *LHSSCEV =
SE.getSCEVAtScope(Load, L);
432 const SCEV *RHSSCEV =
SE.getZero(LHSSCEV->getType());
435 getPwAff(BB, InvalidDomainMap, LHSSCEV, NonNeg, IsInsideDomain)
438 getPwAff(BB, InvalidDomainMap, RHSSCEV, NonNeg, IsInsideDomain)
443 }
else if (
auto *
PHI = dyn_cast<PHINode>(Condition)) {
444 auto *Unique = dyn_cast<ConstantInt>(
447 "A PHINode condition should only be accepted by ScopDetection if "
448 "getUniqueNonErrorValue returns non-NULL");
450 if (Unique->isZero())
454 }
else if (
auto *CCond = dyn_cast<ConstantInt>(Condition)) {
459 }
else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
460 auto Opcode = BinOp->getOpcode();
461 assert(Opcode == Instruction::And || Opcode == Instruction::Or);
465 InvalidDomainMap, ConditionSets, IsInsideDomain) &&
467 InvalidDomainMap, ConditionSets, IsInsideDomain);
469 while (!ConditionSets.empty())
475 isl_set *ConsCondPart0 = ConditionSets.pop_back_val();
477 isl_set *ConsCondPart1 = ConditionSets.pop_back_val();
479 if (Opcode == Instruction::And)
482 ConsequenceCondSet =
isl_set_union(ConsCondPart0, ConsCondPart1);
484 auto *ICond = dyn_cast<ICmpInst>(Condition);
486 "Condition of exiting branch was neither constant nor ICmp!");
488 Region &R =
scop->getRegion();
494 bool NonNeg = ICond->isUnsigned();
495 const SCEV *LeftOperand =
SE.getSCEVAtScope(ICond->getOperand(0), L),
496 *RightOperand =
SE.getSCEVAtScope(ICond->getOperand(1), L);
501 switch (ICond->getPredicate()) {
502 case ICmpInst::ICMP_ULT:
505 LeftOperand, RightOperand, InvalidDomainMap,
506 true, IsInsideDomain)
509 case ICmpInst::ICMP_ULE:
512 LeftOperand, RightOperand, InvalidDomainMap,
513 false, IsInsideDomain)
516 case ICmpInst::ICMP_UGT:
519 RightOperand, LeftOperand, InvalidDomainMap,
520 true, IsInsideDomain)
523 case ICmpInst::ICMP_UGE:
526 RightOperand, LeftOperand, InvalidDomainMap,
527 false, IsInsideDomain)
531 LHS =
getPwAff(BB, InvalidDomainMap, LeftOperand, NonNeg, IsInsideDomain)
533 RHS =
getPwAff(BB, InvalidDomainMap, RightOperand, NonNeg, IsInsideDomain)
546 assert(ConsequenceCondSet);
550 isl_set *AlternativeCondSet =
nullptr;
563 TI ? TI->getParent() :
nullptr );
569 ConditionSets.push_back(ConsequenceCondSet);
577 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
578 SmallVectorImpl<__isl_give isl_set *> &ConditionSets,
bool IsInsideDomain) {
579 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
581 ConditionSets, IsInsideDomain);
583 if (isa<UncondBrInst>(TI)) {
588 Value *Condition = cast<CondBrInst>(TI)->getCondition();
590 ConditionSets, IsInsideDomain);
594 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
604 ReversePostOrderTraversal<Region *> RTraversal(R);
605 for (
auto *RN : RTraversal) {
608 if (RN->isSubRegion()) {
609 Region *SubRegion = RN->getNodeAs<Region>();
610 if (!
scop->isNonAffineSubRegion(SubRegion)) {
627 if (BBLoop && BBLoop->getHeader() == BB &&
scop->contains(BBLoop))
636 BasicBlock *BB, Loop *BBLoop,
637 SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks,
638 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
641 auto *RI =
scop->getRegion().getRegionInfo();
642 auto *BBReg = RI ? RI->getRegionFor(BB) :
nullptr;
643 auto *ExitBB = BBReg ? BBReg->getExit() :
nullptr;
644 if (!BBReg || BBReg->getEntry() != BB || !ExitBB || !
scop->contains(ExitBB))
650 while (L &&
scop->contains(L)) {
651 SmallVector<BasicBlock *, 4> LatchBBs;
652 BBLoop->getLoopLatches(LatchBBs);
653 for (
auto *LatchBB : LatchBBs)
654 if (BB != LatchBB && BBReg->contains(LatchBB))
656 L = L->getParentLoop();
660 assert(!
Domain.is_null() &&
"Cannot propagate a nullptr");
667 isl::set &ExitDomain =
scop->getOrInitEmptyDomain(ExitBB);
672 !ExitDomain.
is_null() ? AdjustedDomain.
unite(ExitDomain) : AdjustedDomain;
675 InvalidDomainMap[ExitBB] = ExitDomain.
empty(ExitDomain.
get_space());
677 FinishedExitBlocks.insert(ExitBB);
683 if (
scop->getRegion().getEntry() == BB)
687 auto &RI = *
scop->getRegion().getRegionInfo();
697 SmallPtrSet<Region *, 8> PropagatedRegions;
699 for (
auto *PredBB : predecessors(BB)) {
701 if (
DT.dominates(BB, PredBB))
705 auto PredBBInRegion = [PredBB](Region *PR) {
return PR->contains(PredBB); };
706 if (llvm::any_of(PropagatedRegions, PredBBInRegion)) {
714 auto *PredR = RI.getRegionFor(PredBB);
715 while (PredR->getExit() != BB && !PredR->contains(BB))
716 PredR = PredR->getParent();
720 if (PredR->getExit() == BB) {
721 PredBB = PredR->getEntry();
722 PropagatedRegions.insert(PredR);
729 PredDom = PredDom.
unite(PredBBDom);
736 Loop *L, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
737 int LoopDepth =
scop->getRelativeLoopDepth(L);
738 assert(LoopDepth >= 0 &&
"Loop in region should have at least depth one");
740 BasicBlock *HeaderBB = L->getHeader();
742 isl::set &HeaderBBDom =
scop->getOrInitEmptyDomain(HeaderBB);
752 SmallVector<BasicBlock *, 4> LatchBlocks;
753 L->getLoopLatches(LatchBlocks);
755 for (BasicBlock *LatchBB : LatchBlocks) {
757 if (!
scop->isDomainDefined(LatchBB))
760 isl::set LatchBBDom =
scop->getDomainConditions(LatchBB);
764 Instruction *TI = LatchBB->getTerminator();
765 if (isa<UncondBrInst>(TI))
766 BackedgeCondition = LatchBBDom;
767 else if (
auto *BI = dyn_cast<CondBrInst>(TI)) {
768 SmallVector<isl_set *, 8> ConditionSets;
769 int idx = BI->getSuccessor(0) != HeaderBB;
770 DenseMap<BasicBlock *, isl::set> LatchInvalidDomainMap;
771 LatchInvalidDomainMap[LatchBB] = LatchBBDom.
empty(LatchBBDom.
get_space());
773 LatchInvalidDomainMap, ConditionSets,
775 isl::set LatchInvalidDomain = LatchInvalidDomainMap[LatchBB];
776 InvalidDomainMap[LatchBB] =
777 InvalidDomainMap[LatchBB].
unite(LatchInvalidDomain);
780 InvalidLatchCtx = InvalidLatchCtx.
unite(
786 BackedgeCondition =
isl::manage(ConditionSets[idx]);
788 llvm_unreachable(
"Only branch instructions allowed in loop latches");
790 int LatchLoopDepth =
scop->getRelativeLoopDepth(
LI.getLoopFor(LatchBB));
791 assert(LatchLoopDepth >= LoopDepth);
792 BackedgeCondition = BackedgeCondition.project_out(
794 UnionBackedgeCondition = UnionBackedgeCondition.
unite(BackedgeCondition);
798 for (
int i = 0; i < LoopDepth; i++)
801 isl::set UnionBackedgeConditionComplement =
803 UnionBackedgeConditionComplement =
804 UnionBackedgeConditionComplement.lower_bound_si(
isl::dim::set, LoopDepth,
806 UnionBackedgeConditionComplement =
807 UnionBackedgeConditionComplement.
apply(ForwardMap);
808 HeaderBBDom = HeaderBBDom.
subtract(UnionBackedgeConditionComplement);
809 HeaderBBDom = HeaderBBDom.
apply(NextIterationMap);
812 HeaderBBDom = Parts.second;
817 bool RequiresRTC = !
scop->hasNSWAddRecForLoop(L);
829 if (!InvalidUnboundedCtx.
is_empty()) {
833 UnboundedCtx = UnboundedCtx.
subtract(InvalidUnboundedCtx);
839 nullptr, RequiresRTC);
844 DenseMap<std::pair<const SCEV *, Type *>, LoadInst *> EquivClasses;
847 for (LoadInst *LInst : RIL) {
848 const SCEV *PointerSCEV =
SE.getSCEV(LInst->getPointerOperand());
850 Type *Ty = LInst->getType();
851 LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)];
853 scop->addInvariantLoadMapping(LInst, ClassRep);
858 scop->addInvariantEquivClass(
864 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
865 bool IsOnlyNonAffineRegion =
scop->isNonAffineSubRegion(R);
866 auto *EntryBB = R->getEntry();
867 auto *L = IsOnlyNonAffineRegion ? nullptr :
LI.getLoopFor(EntryBB);
868 int LD =
scop->getRelativeLoopDepth(L);
876 if (IsOnlyNonAffineRegion)
904 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
916 SmallPtrSet<BasicBlock *, 8> FinishedExitBlocks;
917 ReversePostOrderTraversal<Region *> RTraversal(R);
918 for (
auto *RN : RTraversal) {
921 if (RN->isSubRegion()) {
922 Region *SubRegion = RN->getNodeAs<Region>();
923 if (!
scop->isNonAffineSubRegion(SubRegion)) {
931 scop->notifyErrorBlock();
935 Instruction *TI = BB->getTerminator();
937 if (isa<UnreachableInst>(TI))
940 if (!
scop->isDomainDefined(BB))
957 auto IsFinishedRegionExit = [&FinishedExitBlocks](BasicBlock *SuccBB) {
958 return FinishedExitBlocks.count(SuccBB);
960 if (std::all_of(succ_begin(BB), succ_end(BB), IsFinishedRegionExit))
967 SmallVector<isl_set *, 8> ConditionSets;
968 if (RN->isSubRegion())
969 ConditionSets.push_back(
Domain.copy());
971 ConditionSets,
false))
978 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
979 for (
unsigned u = 0, e = ConditionSets.size(); u < e; u++) {
984 if (!
scop->contains(SuccBB))
989 if (FinishedExitBlocks.count(SuccBB))
993 if (
DT.dominates(SuccBB, BB))
1004 isl::set &SuccDomain =
scop->getOrInitEmptyDomain(SuccBB);
1011 SuccDomain = CondSet;
1022 while (++u < ConditionSets.size())
1032 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1033 ReversePostOrderTraversal<Region *> RTraversal(R);
1034 for (
auto *RN : RTraversal) {
1038 if (RN->isSubRegion()) {
1039 Region *SubRegion = RN->getNodeAs<Region>();
1040 if (!
scop->isNonAffineSubRegion(SubRegion)) {
1049 assert(!
Domain.is_null() &&
"Cannot propagate a nullptr");
1051 isl::set InvalidDomain = InvalidDomainMap[BB];
1053 bool IsInvalidBlock = ContainsErrorBlock ||
Domain.is_subset(InvalidDomain);
1055 if (!IsInvalidBlock) {
1066 InvalidDomainMap[BB] = InvalidDomain;
1071 auto *TI = BB->getTerminator();
1072 unsigned NumSuccs = RN->isSubRegion() ? 1 : TI->getNumSuccessors();
1073 for (
unsigned u = 0; u < NumSuccs; u++) {
1077 if (!
scop->contains(SuccBB))
1081 if (
DT.dominates(SuccBB, BB))
1087 auto AdjustedInvalidDomain =
1090 isl::set SuccInvalidDomain = InvalidDomainMap[SuccBB];
1091 SuccInvalidDomain = SuccInvalidDomain.
unite(AdjustedInvalidDomain);
1092 SuccInvalidDomain = SuccInvalidDomain.
coalesce();
1094 InvalidDomainMap[SuccBB] = SuccInvalidDomain;
1102 InvalidDomainMap.erase(BB);
1103 scop->invalidate(
COMPLEXITY, TI->getDebugLoc(), TI->getParent());
1107 InvalidDomainMap[BB] = InvalidDomain;
1114 Region *NonAffineSubRegion,
1124 auto *Scope =
LI.getLoopFor(
PHI->getParent());
1131 bool OnlyNonAffineSubRegionOperands =
true;
1132 for (
unsigned u = 0; u <
PHI->getNumIncomingValues(); u++) {
1133 Value *Op =
PHI->getIncomingValue(u);
1134 BasicBlock *OpBB =
PHI->getIncomingBlock(u);
1139 if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB)) {
1140 auto *OpInst = dyn_cast<Instruction>(Op);
1141 if (!OpInst || !NonAffineSubRegion->contains(OpInst))
1146 OnlyNonAffineSubRegionOperands =
false;
1150 if (!OnlyNonAffineSubRegionOperands && !IsExitBlock) {
1156 Instruction *Inst) {
1157 assert(!isa<PHINode>(Inst));
1160 for (Use &Op : Inst->operands())
1173 return Prev.sequence(Succ);
1204 Result = Result.add_pw_multi_aff(PMA);
1214 assert(LoopStack.size() == 1 && LoopStack.back().L == L);
1215 scop->setScheduleTree(LoopStack[0].Schedule);
1245 ReversePostOrderTraversal<Region *> RTraversal(R);
1246 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end());
1247 std::deque<RegionNode *> DelayList;
1248 bool LastRNWaiting =
false;
1257 while (!WorkList.empty() || !DelayList.empty()) {
1260 if ((LastRNWaiting && !WorkList.empty()) || DelayList.empty()) {
1261 RN = WorkList.front();
1262 WorkList.pop_front();
1263 LastRNWaiting =
false;
1265 RN = DelayList.front();
1266 DelayList.pop_front();
1270 if (!
scop->contains(L))
1273 Loop *LastLoop = LoopStack.back().L;
1274 if (LastLoop != L) {
1275 if (LastLoop && !LastLoop->contains(L)) {
1276 LastRNWaiting =
true;
1277 DelayList.push_back(RN);
1280 LoopStack.push_back({L, {}, 0});
1287 if (RN->isSubRegion()) {
1288 auto *LocalRegion = RN->getNodeAs<Region>();
1289 if (!
scop->isNonAffineSubRegion(LocalRegion)) {
1295 assert(LoopStack.rbegin() != LoopStack.rend());
1296 auto LoopData = LoopStack.rbegin();
1299 for (
auto *Stmt :
scop->getStmtListFor(RN)) {
1314 size_t Dimension = LoopStack.size();
1315 while (LoopData->L &&
1318 auto NumBlocksProcessed = LoopData->NumBlocksProcessed;
1320 assert(std::next(LoopData) != LoopStack.rend());
1321 Loop *L = LoopData->L;
1328 Schedule = Schedule.insert_partial_schedule(MUPA);
1337 scop->markDisableHeuristics();
1349 LoopData->NumBlocksProcessed += NumBlocksProcessed;
1352 LoopStack.erase(LoopStack.begin() + Dimension, LoopStack.end());
1369 if (
scop->isEscaping(Inst))
1380 if (AS.BB && !AS.Set.is_params()) {
1396 S = std::move(
S).intersect(std::move(Dom));
1398 S = std::move(Dom).subtract(std::move(
S));
1429 S.get_space().universe_set().intersect_params(PSet);
1431 "Must not overapproximate assumptions/restructions");
1435 scop->addAssumption(AS.Kind, std::move(PSet), AS.Loc, Sign, AS.BB,
1441 AssumptionCache &AC, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1443 auto *CI = dyn_cast_or_null<CallInst>(
Assumption);
1444 if (!CI || CI->arg_size() != 1)
1447 bool InScop =
scop->contains(CI);
1448 if (!InScop && !
scop->isDominatedBy(
DT, CI->getParent()))
1451 auto *L =
LI.getLoopFor(CI->getParent());
1452 auto *Val = CI->getArgOperand(0);
1454 auto &R =
scop->getRegion();
1457 OptimizationRemarkAnalysis(
DEBUG_TYPE,
"IgnoreUserAssumption", CI)
1458 <<
"Non-affine user assumption ignored.");
1464 for (
auto *Param : DetectedParams) {
1466 Param =
scop->getRepresentingInvariantLoadSCEV(Param);
1467 if (
scop->isParam(Param))
1469 NewParams.insert(Param);
1472 SmallVector<isl_set *, 2> ConditionSets;
1473 auto *TI = InScop ? CI->getParent()->getTerminator() :
nullptr;
1474 BasicBlock *BB = InScop ? CI->getParent() : R.getEntry();
1481 if (!InvalidDomainMap.count(BB))
1486 assert(Dom &&
"Cannot propagate a nullptr.");
1493 isl::set BBInvalidDomain = InvalidDomainMap[BB];
1494 assert(!BBInvalidDomain.
is_null() &&
"Cannot propagate a nullptr.");
1495 DenseMap<BasicBlock *, isl::set> AssumptionInvalidDomainMap;
1496 AssumptionInvalidDomainMap[BB] =
1499 AssumptionInvalidDomainMap, ConditionSets);
1502 isl::set AssumptionInvalidDomain = AssumptionInvalidDomainMap[BB];
1503 bool HasPreconditions = !AssumptionInvalidDomain.
is_empty();
1504 InvalidDomainMap[BB] = BBInvalidDomain.
unite(AssumptionInvalidDomain);
1509 isl_set *AssumptionCtx =
nullptr;
1519 if (!NewParams.empty()) {
1525 if (!NewParams.count(Param))
1532 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"UserAssumption", CI)
1533 <<
"Use user assumption: "
1534 << stringFromIslObj(AssumptionCtx,
"null"));
1541 if (!HasPreconditions) {
1544 scop->setContext(newContext);
1557 Type *ElementType = Val->getType();
1559 const SCEV *AccessFunction =
1560 SE.getSCEVAtScope(Address,
LI.getLoopFor(Inst->getParent()));
1561 const SCEVUnknown *BasePointer =
1562 dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1566 if (
auto *BitCast = dyn_cast<BitCastInst>(Address))
1567 Address = BitCast->getOperand(0);
1569 auto *GEP = dyn_cast<GetElementPtrInst>(Address);
1570 if (!GEP ||
DL.getTypeAllocSize(GEP->getResultElementType()) !=
1571 DL.getTypeAllocSize(ElementType))
1574 SmallVector<const SCEV *, 4> Subscripts;
1575 SmallVector<const SCEV *, 4> Sizes;
1576 getIndexExpressionsFromGEP(
SE, GEP, Subscripts, Sizes);
1577 auto *BasePtr = GEP->getOperand(0);
1579 if (
auto *BasePtrCast = dyn_cast<BitCastInst>(BasePtr))
1580 BasePtr = BasePtrCast->getOperand(0);
1584 if (BasePtr != BasePointer->getValue())
1590 for (
auto *Subscript : Subscripts) {
1596 for (LoadInst *LInst : AccessILS)
1597 if (!ScopRIL.count(LInst))
1604 std::vector<const SCEV *> SizesSCEV;
1605 SizesSCEV.push_back(
nullptr);
1606 SizesSCEV.insert(SizesSCEV.end(), Sizes.begin(), Sizes.end());
1608 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1609 true, Subscripts, SizesSCEV, Val);
1623 Type *ElementType = Val->getType();
1624 unsigned ElementSize =
DL.getTypeAllocSize(ElementType);
1628 const SCEV *AccessFunction =
1629 SE.getSCEVAtScope(Address,
LI.getLoopFor(Inst->getParent()));
1630 const SCEVUnknown *BasePointer =
1631 dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1633 assert(BasePointer &&
"Could not find base pointer");
1635 auto &InsnToMemAcc =
scop->getInsnToMemAccMap();
1636 auto AccItr = InsnToMemAcc.find(Inst);
1637 if (AccItr == InsnToMemAcc.end())
1640 std::vector<const SCEV *> Sizes = {
nullptr};
1642 Sizes.insert(Sizes.end(), AccItr->second.Shape->DelinearizedSizes.begin(),
1643 AccItr->second.Shape->DelinearizedSizes.end());
1648 if (Sizes.size() == 1)
1657 auto DelinearizedSize =
1658 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue();
1660 if (ElementSize != DelinearizedSize)
1663 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1664 true, AccItr->second.DelinearizedSubscripts, Sizes, Val);
1669 auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst);
1671 if (MemIntr ==
nullptr)
1674 auto *L =
LI.getLoopFor(Inst->getParent());
1675 const SCEV *LengthVal =
SE.getSCEVAtScope(MemIntr->getLength(), L);
1684 LengthVal,
SE, &AccessILS);
1685 for (LoadInst *LInst : AccessILS)
1686 if (!ScopRIL.count(LInst))
1687 LengthIsAffine =
false;
1688 if (!LengthIsAffine)
1689 LengthVal =
nullptr;
1691 auto *DestPtrVal = MemIntr->getDest();
1694 const SCEV *DestAccFunc =
SE.getSCEVAtScope(DestPtrVal, L);
1701 if (DestAccFunc->isZero())
1704 if (
auto *U = dyn_cast<SCEVUnknown>(DestAccFunc)) {
1705 if (isa<ConstantPointerNull>(U->getValue()))
1709 auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(
SE.getPointerBase(DestAccFunc));
1711 DestAccFunc =
SE.getMinusSCEV(DestAccFunc, DestPtrSCEV);
1713 IntegerType::getInt8Ty(DestPtrVal->getContext()),
1714 LengthIsAffine, {DestAccFunc, LengthVal}, {nullptr},
1717 auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr);
1721 auto *SrcPtrVal = MemTrans->getSource();
1724 const SCEV *SrcAccFunc =
SE.getSCEVAtScope(SrcPtrVal, L);
1728 if (SrcAccFunc->isZero())
1731 auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(
SE.getPointerBase(SrcAccFunc));
1733 SrcAccFunc =
SE.getMinusSCEV(SrcAccFunc, SrcPtrSCEV);
1735 IntegerType::getInt8Ty(SrcPtrVal->getContext()),
1736 LengthIsAffine, {SrcAccFunc, LengthVal}, {nullptr},
1743 auto *CI = dyn_cast_or_null<CallInst>(Inst);
1751 const SCEV *AF =
SE.getConstant(IntegerType::getInt64Ty(CI->getContext()), 0);
1752 auto *CalledFunction = CI->getCalledFunction();
1753 MemoryEffects ME =
AA.getMemoryEffects(CalledFunction);
1754 if (ME.doesNotAccessMemory())
1757 if (ME.onlyAccessesArgPointees()) {
1758 ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
1761 Loop *L =
LI.getLoopFor(Inst->getParent());
1762 for (
const auto &Arg : CI->args()) {
1763 if (!Arg->getType()->isPointerTy())
1766 const SCEV *ArgSCEV =
SE.getSCEVAtScope(Arg, L);
1767 if (ArgSCEV->isZero())
1770 if (
auto *U = dyn_cast<SCEVUnknown>(ArgSCEV)) {
1771 if (isa<ConstantPointerNull>(U->getValue()))
1775 auto *ArgBasePtr = cast<SCEVUnknown>(
SE.getPointerBase(ArgSCEV));
1777 ArgBasePtr->getType(),
false, {AF}, {nullptr}, CI);
1782 if (ME.onlyReadsMemory()) {
1796 Type *ElementType = Val->getType();
1800 const SCEV *AccessFunction =
1801 SE.getSCEVAtScope(Address,
LI.getLoopFor(Inst->getParent()));
1802 const SCEVUnknown *BasePointer =
1803 dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1805 assert(BasePointer &&
"Could not find base pointer");
1806 AccessFunction =
SE.getMinusSCEV(AccessFunction, BasePointer);
1809 bool isVariantInNonAffineLoop =
false;
1810 SetVector<const Loop *> Loops;
1812 for (
const Loop *L : Loops)
1814 isVariantInNonAffineLoop =
true;
1821 bool IsAffine = !isVariantInNonAffineLoop &&
1823 AccessFunction,
SE, &AccessILS);
1826 for (LoadInst *LInst : AccessILS)
1827 if (!ScopRIL.count(LInst))
1833 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1834 IsAffine, {AccessFunction}, {nullptr}, Val);
1855 "At least one of the buildAccess functions must handled this access, or "
1856 "ScopDetection should have rejected this SCoP");
1860 for (
auto &Stmt : *
scop) {
1861 if (Stmt.isBlockStmt()) {
1866 Region *R = Stmt.getRegion();
1867 for (BasicBlock *BB : R->blocks())
1875 for (BasicBlock *BB :
scop->getRegion().blocks()) {
1876 for (Instruction &Inst : *BB)
1895 bool IsMain,
bool IsLast =
false) {
1902 else if (Count < 26)
1903 Suffix +=
'a' + Count;
1905 Suffix += std::to_string(Count);
1920 Loop *SurroundingLoop =
LI.getLoopFor(BB);
1923 long BBIdx =
scop->getNextStmtIdx();
1924 std::vector<Instruction *> Instructions;
1925 for (Instruction &Inst : *BB) {
1927 Instructions.push_back(&Inst);
1928 if (Inst.getMetadata(
"polly_split_after") ||
1929 (SplitOnStore && isa<StoreInst>(Inst))) {
1930 std::string Name =
makeStmtName(BB, BBIdx, Count, Count == 0);
1931 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1933 Instructions.clear();
1937 std::string Name =
makeStmtName(BB, BBIdx, Count, Count == 0);
1938 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1947 return Inst->mayHaveSideEffects() || Inst->mayReadOrWriteMemory();
1953 ArrayRef<Instruction *> ModeledInsts) {
1954 for (Instruction *Inst : ModeledInsts) {
1955 if (isa<PHINode>(Inst))
1958 for (Use &Op : Inst->operands()) {
1959 Instruction *OpInst = dyn_cast<Instruction>(Op.get());
1964 if (!UnionFind.contains(OpInst))
1967 UnionFind.unionSets(Inst, OpInst);
1979 ArrayRef<Instruction *> ModeledInsts) {
1980 SetVector<Instruction *> SeenLeaders;
1981 for (Instruction *Inst : ModeledInsts) {
1985 Instruction *Leader = UnionFind.getLeaderValue(Inst);
1990 bool Inserted = SeenLeaders.insert(Leader);
1998 for (Instruction *Prev : reverse(SeenLeaders)) {
2006 UnionFind.unionSets(Prev, Leader);
2030 ArrayRef<Instruction *> ModeledInsts) {
2031 for (Instruction *Inst : ModeledInsts) {
2032 PHINode *
PHI = dyn_cast<PHINode>(Inst);
2036 int Idx =
PHI->getBasicBlockIndex(
PHI->getParent());
2040 Instruction *IncomingVal =
2041 dyn_cast<Instruction>(
PHI->getIncomingValue(Idx));
2045 UnionFind.unionSets(
PHI, IncomingVal);
2050 Loop *L =
LI.getLoopFor(BB);
2054 SmallVector<Instruction *, 32> ModeledInsts;
2055 EquivalenceClasses<Instruction *> UnionFind;
2056 Instruction *MainInst =
nullptr, *MainLeader =
nullptr;
2057 for (Instruction &Inst : *BB) {
2060 ModeledInsts.push_back(&Inst);
2061 UnionFind.insert(&Inst);
2068 if (!MainInst && (isa<StoreInst>(Inst) ||
2069 (isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst))))
2079 MapVector<Instruction *, std::vector<Instruction *>> LeaderToInstList;
2084 for (Instruction *Inst : ModeledInsts) {
2088 auto LeaderIt = UnionFind.findLeader(Inst);
2089 if (LeaderIt == UnionFind.member_end())
2093 (void)LeaderToInstList[*LeaderIt];
2098 for (Instruction *Inst : ModeledInsts) {
2099 auto LeaderIt = UnionFind.findLeader(Inst);
2100 if (LeaderIt == UnionFind.member_end())
2103 if (Inst == MainInst)
2104 MainLeader = *LeaderIt;
2105 std::vector<Instruction *> &InstList = LeaderToInstList[*LeaderIt];
2106 InstList.push_back(Inst);
2111 long BBIdx =
scop->getNextStmtIdx();
2112 for (
auto &Instructions : LeaderToInstList) {
2113 std::vector<Instruction *> &InstList = Instructions.second;
2116 bool IsMain = (MainInst ? MainLeader == Instructions.first : Count == 0);
2118 std::string Name =
makeStmtName(BB, BBIdx, Count, IsMain);
2119 scop->addScopStmt(BB, Name, L, std::move(InstList));
2129 std::string EpilogueName =
makeStmtName(BB, BBIdx, Count, Count == 0,
true);
2130 scop->addScopStmt(BB, EpilogueName, L, {});
2134 if (
scop->isNonAffineSubRegion(&SR)) {
2135 std::vector<Instruction *> Instructions;
2136 Loop *SurroundingLoop =
2138 for (Instruction &Inst : *SR.getEntry())
2140 Instructions.push_back(&Inst);
2141 long RIdx =
scop->getNextStmtIdx();
2143 scop->addScopStmt(&SR, Name, SurroundingLoop, Instructions);
2147 for (
auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
2148 if (I->isSubRegion())
2151 BasicBlock *BB = I->getNodeAs<BasicBlock>();
2167 Region *NonAffineSubRegion) {
2170 "The exit BB is the only one that cannot be represented by a statement");
2175 if (
SD.isErrorBlock(BB,
scop->getRegion()))
2178 auto BuildAccessesForInst = [
this, Stmt,
2179 NonAffineSubRegion](Instruction *Inst) {
2180 PHINode *
PHI = dyn_cast<PHINode>(Inst);
2185 assert(Stmt &&
"Cannot build access function in non-existing statement");
2201 BuildAccessesForInst(Inst);
2203 BuildAccessesForInst(BB.getTerminator());
2205 for (Instruction &Inst : BB) {
2210 if (isa<LoadInst>(Inst) && RIL.count(cast<LoadInst>(&Inst)))
2213 BuildAccessesForInst(&Inst);
2220 Value *BaseAddress, Type *ElementType,
bool Affine,
Value *AccessValue,
2221 ArrayRef<const SCEV *> Subscripts, ArrayRef<const SCEV *> Sizes,
2223 bool isKnownMustAccess =
false;
2227 isKnownMustAccess =
true;
2235 if (Inst &&
DT.dominates(Inst->getParent(), Stmt->
getRegion()->getExit()))
2236 isKnownMustAccess =
true;
2243 isKnownMustAccess =
true;
2248 auto *Access =
new MemoryAccess(Stmt, Inst, AccType, BaseAddress, ElementType,
2249 Affine, Subscripts, Sizes, AccessValue,
Kind);
2251 scop->addAccessFunction(Access);
2258 Value *BaseAddress, Type *ElementType,
2260 ArrayRef<const SCEV *> Subscripts,
2261 ArrayRef<const SCEV *> Sizes,
2262 Value *AccessValue) {
2269static bool isDivisible(
const SCEV *Expr,
unsigned Size, ScalarEvolution &SE) {
2275 if (
auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
2276 for (
const SCEV *FactorExpr : MulExpr->operands())
2284 if (
auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
2285 for (
const SCEV *OpExpr : NAryExpr->operands())
2291 const SCEV *SizeSCEV = SE.getConstant(Expr->getType(), Size);
2292 const SCEV *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV);
2293 const SCEV *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV);
2294 return MulSCEV == Expr;
2301 if (
Array->getNumberOfDimensions() <= 1)
2305 Space = Space.align_params(Accessed.
get_space());
2307 if (!Accessed.contains(Space))
2313 std::vector<int> Int;
2315 for (
unsigned i = 0; i < Dims; i++) {
2317 DimOnly = DimOnly.project_out(
isl::dim::set, 1, Dims - i - 1);
2322 if (i == Dims - 1) {
2329 isl::aff Diff = DimHull.get_div(0);
2330 isl::val Val = Diff.get_denominator_val();
2335 if (ValAPInt.isSignedIntN(32))
2336 ValInt = ValAPInt.getSExtValue();
2340 Int.push_back(ValInt);
2345 Transform = Transform.add_constraint(
C);
2357 Int.push_back(ValInt);
2362 if (!Elements.
is_subset(MappedElements))
2365 bool CanFold =
true;
2369 unsigned NumDims =
Array->getNumberOfDimensions();
2370 for (
unsigned i = 1; i < NumDims - 1; i++)
2371 if (Int[0] != Int[i] && Int[i])
2377 for (
auto &Access :
scop->access_functions())
2378 if (Access->getScopArrayInfo() ==
Array)
2379 Access->setAccessRelation(
2380 Access->getAccessRelation().apply_range(Transform));
2382 std::vector<const SCEV *> Sizes;
2383 for (
unsigned i = 0; i < NumDims; i++) {
2384 auto Size =
Array->getDimensionSize(i);
2386 if (i == NumDims - 1)
2387 Size =
SE.getMulExpr(Size,
SE.getConstant(Size->getType(), Int[0]));
2388 Sizes.push_back(Size);
2391 Array->updateSizes(Sizes,
false );
2407 if (!Access->isArrayKind())
2412 if (
Array->getNumberOfDimensions() != 1)
2414 unsigned DivisibleSize =
Array->getElemSizeInBytes();
2415 const SCEV *Subscript = Access->getSubscript(0);
2418 auto *Ty = IntegerType::get(
SE.getContext(), DivisibleSize * 8);
2419 Array->updateElementType(Ty);
2422 for (
auto &Stmt : *
scop)
2423 for (
auto &Access : Stmt)
2424 Access->updateDimensionality();
2428 for (
auto &Stmt : *
scop)
2429 for (
auto &Access : Stmt)
2430 Access->foldAccessRelation();
2436 for (
auto &Stmt : *
scop)
2437 for (
auto &Access : Stmt) {
2438 isl::set Outside = Access->assumeNoOutOfBound();
2439 const auto &Loc = Access->getAccessInstruction()
2440 ? Access->getAccessInstruction()->getDebugLoc()
2458 Stmt =
scop->getLastStmtFor(Inst->getParent());
2469 true, Inst, ArrayRef<const SCEV *>(),
2485 switch (VUse.getKind()) {
2508 true, V, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2519 BasicBlock *IncomingBlock,
2520 Value *IncomingValue,
bool IsExitBlock) {
2525 scop->getOrCreateScopArrayInfo(
PHI,
PHI->getType(), {},
2542 assert(Acc->getAccessInstruction() ==
PHI);
2543 Acc->addIncoming(IncomingBlock, IncomingValue);
2549 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2557 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2564 Stmt.
Domain =
scop->getDomainConditions(&Stmt);
2572 Loop *L =
LI.getLoopFor(BB);
2575 L = L->getParentLoop();
2577 SmallVector<llvm::Loop *, 8> Loops;
2581 L = L->getParentLoop();
2592 switch (BinOp->getOpcode()) {
2593 case Instruction::FAdd:
2594 if (!BinOp->isFast())
2597 case Instruction::Add:
2599 case Instruction::Or:
2601 case Instruction::Xor:
2603 case Instruction::And:
2605 case Instruction::FMul:
2606 if (!BinOp->isFast())
2609 case Instruction::Mul:
2633 SmallVector<MemoryAccess *, 8> &MemAccs) {
2634 bool HasIntersectingAccs =
false;
2638 if (MA == LoadMA || MA == StoreMA)
2640 auto AccRel = MA->getAccessRelation().intersect_domain(
Domain);
2641 auto Accs = AccRel.range();
2642 auto AccsNoParams = Accs.project_out_all_params();
2644 bool CompatibleSpace = AllAccsNoParams.has_equal_space(AccsNoParams);
2646 if (CompatibleSpace) {
2647 auto OverlapAccs = Accs.intersect(AllAccs);
2648 bool DoesIntersect = !OverlapAccs.is_empty();
2649 HasIntersectingAccs |= DoesIntersect;
2652 return HasIntersectingAccs;
2658 SmallVector<MemoryAccess *, 8> &MemAccs) {
2662 bool Valid = LoadAccs.has_equal_space(StoreAccs);
2663 POLLY_DEBUG(dbgs() <<
" == The accessed space below is "
2664 << (Valid ?
"" :
"not ") <<
"equal!\n");
2679 POLLY_DEBUG(dbgs() <<
" == The accessed memory is " << (Valid ?
"" :
"not ")
2680 <<
"overlapping!\n");
2689 POLLY_DEBUG(dbgs() <<
" == The accessed memory is " << (Valid ?
"not " :
"")
2690 <<
"accessed by other instructions!\n");
2704 using StatePairTy = std::pair<unsigned, MemoryAccess::ReductionType>;
2705 using FlowInSetTy = MapVector<const LoadInst *, StatePairTy>;
2706 using StateTy = MapVector<const Instruction *, FlowInSetTy>;
2718 SmallPtrSet<const Instruction *, 8> InvalidLoads;
2719 SmallVector<BasicBlock *, 8> ScopBlocks;
2722 ScopBlocks.push_back(BB);
2724 for (BasicBlock *Block : Stmt.
getRegion()->blocks())
2725 ScopBlocks.push_back(Block);
2727 for (BasicBlock *Block : ScopBlocks) {
2728 for (Instruction &Inst : *Block) {
2729 if ((Stmt.
getParent())->getStmtFor(&Inst) != &Stmt)
2731 bool UsedOutsideStmt = any_of(Inst.users(), [&Stmt](User *U) {
2732 return (Stmt.getParent())->getStmtFor(cast<Instruction>(U)) != &Stmt;
2735 if (
auto *Load = dyn_cast<LoadInst>(&Inst)) {
2737 if (
auto *Ptr = dyn_cast<Instruction>(Load->getPointerOperand())) {
2738 const auto &It = State.find(Ptr);
2739 if (It != State.end())
2740 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2744 if (UsedOutsideStmt)
2745 InvalidLoads.insert(Load);
2754 if (
auto *Store = dyn_cast<StoreInst>(&Inst)) {
2756 if (
const Instruction *Ptr =
2757 dyn_cast<Instruction>(Store->getPointerOperand())) {
2758 const auto &It = State.find(Ptr);
2759 if (It != State.end())
2760 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2764 if (
auto *ValueInst = dyn_cast<Instruction>(Store->getValueOperand()))
2765 State.insert(std::make_pair(Store, State[ValueInst]));
2771 auto *BinOp = dyn_cast<BinaryOperator>(&Inst);
2773 POLLY_DEBUG(dbgs() <<
"CurInst: " << Inst <<
" RT: " << CurRedType
2778 FlowInSetTy &InstInFlowSet = State[&Inst];
2779 for (Use &Op : Inst.operands()) {
2780 auto *OpInst = dyn_cast<Instruction>(Op);
2784 POLLY_DEBUG(dbgs().indent(4) <<
"Op Inst: " << *OpInst <<
"\n");
2785 const StateTy::iterator &OpInFlowSetIt = State.find(OpInst);
2786 if (OpInFlowSetIt == State.end())
2791 FlowInSetTy &OpInFlowSet = OpInFlowSetIt->second;
2792 for (
auto &OpInFlowPair : OpInFlowSet) {
2793 unsigned OpFlowIn = OpInFlowPair.second.first;
2794 unsigned InstFlowIn = InstInFlowSet[OpInFlowPair.first].first;
2798 InstInFlowSet[OpInFlowPair.first].second;
2805 POLLY_DEBUG(dbgs().indent(8) <<
"OpRedType: " << OpRedType <<
"\n");
2806 POLLY_DEBUG(dbgs().indent(8) <<
"NewRedType: " << NewRedType <<
"\n");
2807 InstInFlowSet[OpInFlowPair.first] =
2808 std::make_pair(OpFlowIn + InstFlowIn, NewRedType);
2814 if (UsedOutsideStmt)
2815 InvalidLoads.insert_range(llvm::make_first_range(InstInFlowSet));
2824 using MemAccPair = std::pair<MemoryAccess *, MemoryAccess *>;
2825 DenseMap<MemAccPair, MemoryAccess::ReductionType> ValidCandidates;
2835 assert(!St->isVolatile());
2838 for (
auto &MaInFlowSetElem : MaInFlowSet) {
2840 assert(ReadMA &&
"Couldn't find memory access for incoming load!");
2843 <<
"'\n\tflows into\n'"
2845 << MaInFlowSetElem.second.first <<
" times & RT: "
2846 << MaInFlowSetElem.second.second <<
"\n");
2849 unsigned NumAllowableInFlow = 1;
2852 bool Valid = (MaInFlowSetElem.second.first == NumAllowableInFlow);
2864 ValidCandidates[std::make_pair(ReadMA, WriteMA)] = RT;
2872 for (
auto &CandidatePair : ValidCandidates) {
2877 dbgs() <<
" Load :: "
2878 << *((CandidatePair.first.first)->getAccessInstruction())
2880 << *((CandidatePair.first.second)->getAccessInstruction())
2881 <<
"\n are marked as reduction like\n");
2883 CandidatePair.first.first->markAsReductionLike(RT);
2884 CandidatePair.first.second->markAsReductionLike(RT);
2889 auto &RIL =
scop->getRequiredInvariantLoads();
2890 for (LoadInst *
LI : RIL) {
2895 if (Stmt.getArrayAccessOrNULLFor(
LI)) {
2913 InvariantAccesses.push_back({Access, NHCtx});
2917 for (
auto InvMA : InvariantAccesses)
2918 Stmt.removeMemoryAccess(InvMA.MA);
2936 unsigned NumTotalDims = 0;
2951 if (
auto *BasePtrMA =
scop->lookupBasePtrAccess(MA)) {
2956 if (
auto *BasePtrInst = dyn_cast<Instruction>(BaseAddr))
2957 if (!isa<LoadInst>(BasePtrInst))
2958 return scop->contains(BasePtrInst);
2972 std::string SpaceStr = stringFromIslObj(Space,
"null");
2973 errs() <<
"Error: the context provided in -polly-context has not the same "
2974 <<
"number of dimensions than the computed context. Due to this "
2975 <<
"mismatch, the -polly-context option is ignored. Please provide "
2976 <<
"the context in the parameter space: " << SpaceStr <<
".\n";
2981 std::string NameContext =
2983 std::string NameUserContext = UserContext.get_dim_name(
isl::dim::param, i);
2985 if (NameContext != NameUserContext) {
2986 std::string SpaceStr = stringFromIslObj(Space,
"null");
2987 errs() <<
"Error: the name of dimension " << i
2988 <<
" provided in -polly-context "
2989 <<
"is '" << NameUserContext <<
"', but the name in the computed "
2990 <<
"context is '" << NameContext
2991 <<
"'. Due to this name mismatch, "
2992 <<
"the -polly-context option is ignored. Please provide "
2993 <<
"the context in the parameter space: " << SpaceStr <<
".\n";
3000 isl::set newContext =
scop->getContext().intersect(UserContext);
3001 scop->setContext(newContext);
3035 if (AccessRelation.involves_dims(
isl::dim::in, 0, Stmt.getNumIterators()))
3041 auto &
DL =
scop->getFunction().getDataLayout();
3042 if (isSafeToLoadUnconditionally(
LI->getPointerOperand(),
LI->getType(),
3043 LI->getAlign(),
DL)) {
3045 }
else if (BB !=
LI->getParent()) {
3050 SafeToLoad = AccessRelation.
range();
3058 bool IsWritten = !WrittenCtx.
is_empty();
3063 WrittenCtx = WrittenCtx.remove_divs();
3075 for (
const llvm::Argument &Arg : F.args())
3076 if (&Arg == maybeParam)
3083 bool StmtInvalidCtxIsEmpty,
3084 bool MAInvalidCtxIsEmpty,
3085 bool NonHoistableCtxIsEmpty) {
3087 const DataLayout &
DL = LInst->getDataLayout();
3094 if (!isDereferenceableAndAlignedPointer(
3095 LInst->getPointerOperand(), LInst->getType(), LInst->getAlign(),
DL))
3101 if (!NonHoistableCtxIsEmpty)
3106 if (StmtInvalidCtxIsEmpty && MAInvalidCtxIsEmpty)
3112 for (
const SCEV *Subscript : MA->
subscripts())
3113 if (!isa<SCEVConstant>(Subscript))
3124 bool StmtInvalidCtxIsEmpty = StmtInvalidCtx.
is_empty();
3129 DomainCtx = DomainCtx.
subtract(StmtInvalidCtx);
3132 auto *AccInst = InvMAs.front().MA->getAccessInstruction();
3133 scop->invalidate(
COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent());
3142 for (
auto &InvMA : InvMAs) {
3143 auto *MA = InvMA.MA;
3144 Instruction *AccInst = MA->getAccessInstruction();
3145 if (
SE.isSCEVable(AccInst->getType())) {
3146 SetVector<Value *> Values;
3147 for (
const SCEV *Parameter :
scop->parameters()) {
3150 if (!Values.count(AccInst))
3163 for (
auto &InvMA : InvMAs) {
3164 auto *MA = InvMA.MA;
3165 isl::set NHCtx = InvMA.NonHoistableCtx;
3170 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
3171 Type *Ty = LInst->getType();
3172 const SCEV *PointerSCEV =
SE.getSCEV(LInst->getPointerOperand());
3174 isl::set MAInvalidCtx = MA->getInvalidContext();
3175 bool NonHoistableCtxIsEmpty = NHCtx.
is_empty();
3176 bool MAInvalidCtxIsEmpty = MAInvalidCtx.
is_empty();
3181 NonHoistableCtxIsEmpty)) {
3189 bool Consolidated =
false;
3190 for (
auto &IAClass :
scop->invariantEquivClasses()) {
3191 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
3199 auto &MAs = IAClass.InvariantAccesses;
3201 auto *LastMA = MAs.front();
3203 isl::set AR = MA->getAccessRelation().range();
3204 isl::set LastAR = LastMA->getAccessRelation().range();
3214 Consolidated =
true;
3217 isl::set IAClassDomainCtx = IAClass.ExecutionContext;
3218 if (!IAClassDomainCtx.
is_null())
3219 IAClassDomainCtx = IAClassDomainCtx.
unite(MACtx).
coalesce();
3221 IAClassDomainCtx = MACtx;
3222 IAClass.ExecutionContext = IAClassDomainCtx;
3233 scop->addInvariantEquivClass(
3248 return CanonicalArray;
3256 for (
MemoryAccess *Access2 : EqClass2.InvariantAccesses)
3268 if (Access->getLatestScopArrayInfo() != Old)
3272 isl::map Map = Access->getAccessRelation();
3274 Access->setAccessRelation(Map);
3285 if (!CanonicalBasePtrSAI)
3291 if (!BasePtrSAI || BasePtrSAI == CanonicalBasePtrSAI ||
3325 for (
const SCEV *Size : Access->
Sizes) {
3331 ElementType, Access->
Sizes, Ty);
3336 for (
const SCEV *Subscript : Access->
subscripts()) {
3337 if (!Access->
isAffine() || !Subscript)
3343 scop->addAccessData(Access);
3358 Set = Set.remove_divs();
3365 Set = Set.simple_hull();
3383 unsigned InvolvedParams = 0;
3407 assert(MaxOutputSize >= 1 &&
"Assumed at least one output dimension");
3409 Pos = MaxOutputSize - 1;
3410 LastDimAff = MaxPMA.
at(Pos);
3412 OneAff = OneAff.add_constant_si(1);
3413 LastDimAff = LastDimAff.
add(OneAff);
3414 MaxPMA = MaxPMA.set_pw_aff(Pos, LastDimAff);
3419 MinMaxAccesses.push_back(std::make_pair(MinPMA, MaxPMA));
3427 MinMaxAccesses.reserve(AliasGroup.size());
3433 Accesses = Accesses.
unite(MA->getAccessRelation());
3438 bool LimitReached =
false;
3445 return !LimitReached;
3452 return Domain.reset_tuple_id();
3462 if (
scop->getAliasGroups().size())
3472 POLLY_DEBUG(dbgs() <<
"\n\nNOTE: Run time checks for " <<
scop->getNameStr()
3473 <<
" could not be created. This SCoP has been dismissed.");
3477std::tuple<ScopBuilder::AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>>
3479 BatchAAResults BAA(
AA);
3480 AliasSetTracker AST(BAA);
3482 DenseMap<Value *, MemoryAccess *> PtrToAcc;
3483 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3486 isl::set StmtDomain = Stmt.getDomain();
3487 bool StmtDomainEmpty = StmtDomain.
is_empty();
3490 if (StmtDomainEmpty)
3494 if (MA->isScalarKind())
3497 HasWriteAccess.insert(MA->getScopArrayInfo());
3499 if (MA->isRead() && isa<MemTransferInst>(Acc))
3500 PtrToAcc[cast<MemTransferInst>(Acc)->getRawSource()] = MA;
3508 for (AliasSet &AS : AST) {
3509 if (AS.isMustAlias() || AS.isForwardingAliasSet())
3512 for (
const Value *Ptr : AS.getPointers())
3513 AG.push_back(PtrToAcc[
const_cast<Value *
>(Ptr)]);
3516 AliasGroups.push_back(std::move(AG));
3519 return std::make_tuple(AliasGroups, HasWriteAccess);
3529 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3536 if (!
scop->hasFeasibleRuntimeContext())
3555 AliasGroupTy &AliasGroup, DenseSet<const ScopArrayInfo *> HasWriteAccess) {
3558 SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays;
3559 SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays;
3561 if (AliasGroup.size() < 2)
3565 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"PossibleAlias",
3566 Access->getAccessInstruction())
3567 <<
"Possibly aliasing pointer, use restrict keyword.");
3569 if (HasWriteAccess.count(
Array)) {
3570 ReadWriteArrays.insert(
Array);
3571 ReadWriteAccesses.push_back(Access);
3573 ReadOnlyArrays.insert(
Array);
3574 ReadOnlyAccesses.push_back(Access);
3580 if (ReadOnlyAccesses.empty() && ReadWriteArrays.size() <= 1)
3584 if (ReadWriteArrays.empty())
3590 if (!MA->isAffine()) {
3591 scop->invalidate(
ALIASING, MA->getAccessInstruction()->getDebugLoc(),
3592 MA->getAccessInstruction()->getParent());
3601 scop->addRequiredInvariantLoad(
3602 cast<LoadInst>(BasePtrMA->getAccessInstruction()));
3620 if (MinMaxAccessesReadWrite.size() + ReadOnlyArrays.size() >
3626 scop->addAliasGroup(MinMaxAccessesReadWrite, MinMaxAccessesReadOnly);
3634 for (
unsigned u = 0; u < AliasGroups.size(); u++) {
3637 AliasGroupTy::iterator AGI = AG.begin();
3639 while (AGI != AG.end()) {
3643 NewAG.push_back(MA);
3644 AGI = AG.erase(AGI);
3646 AGDomain = AGDomain.
unite(MADomain);
3650 if (NewAG.size() > 1)
3651 AliasGroups.push_back(std::move(NewAG));
3659 assert(PhysUse.getKind() == VirtUse.getKind());
3678 for (
auto *BB :
S->getRegion().blocks()) {
3679 for (
auto &Inst : *BB) {
3680 auto *Stmt =
S->getStmtFor(&Inst);
3688 if (Inst.isTerminator() && Stmt->isBlockStmt())
3692 for (
auto &Op : Inst.operands())
3696 if (isa<StoreInst>(Inst))
3711 if (
S->hasSingleExitEdge())
3715 if (!
S->getRegion().isTopLevelRegion()) {
3716 for (
auto &Inst : *
S->getRegion().getExit()) {
3717 if (!isa<PHINode>(Inst))
3720 for (
auto &Op : Inst.operands())
3737 for (BasicBlock *BB :
scop->getRegion().blocks()) {
3738 if (
SD.isErrorBlock(*BB,
scop->getRegion()))
3741 for (Instruction &Inst : *BB) {
3742 LoadInst *Load = dyn_cast<LoadInst>(&Inst);
3746 if (!RIL.count(Load))
3753 ArrayRef<ScopStmt *> List =
scop->getStmtListFor(BB);
3768 if (!R.isTopLevelRegion() && !
scop->hasSingleExitEdge()) {
3769 for (Instruction &Inst : *R.getExit()) {
3770 PHINode *
PHI = dyn_cast<PHINode>(&Inst);
3779 const SCEV *AF =
SE.getConstant(IntegerType::getInt64Ty(
SE.getContext()), 0);
3781 ScopStmt *GlobalReadStmt = GlobalReadPair.first;
3782 Instruction *GlobalRead = GlobalReadPair.second;
3785 BP, BP->getType(),
false, {AF}, {nullptr}, GlobalRead);
3791 DenseMap<BasicBlock *, isl::set> InvalidDomainMap;
3795 dbgs() <<
"Bailing-out because buildDomains encountered problems\n");
3811 scop->removeStmtNotInDomainMap();
3812 scop->simplifySCoP(
false);
3813 if (
scop->isEmpty()) {
3814 POLLY_DEBUG(dbgs() <<
"Bailing-out because SCoP is empty\n");
3830 if (!
scop->hasFeasibleRuntimeContext()) {
3832 dbgs() <<
"Bailing-out because of unfeasible context (early)\n");
3841 dbgs() <<
"Bailing-out because SCoP is not considered profitable\n");
3849 scop->realignParams();
3857 scop->simplifyContexts();
3859 POLLY_DEBUG(dbgs() <<
"Bailing-out because could not build alias checks\n");
3866 scop->simplifySCoP(
true);
3870 if (!
scop->hasFeasibleRuntimeContext()) {
3871 POLLY_DEBUG(dbgs() <<
"Bailing-out because of unfeasible context (late)\n");
3881 const DataLayout &
DL, DominatorTree &
DT, LoopInfo &
LI,
3883 OptimizationRemarkEmitter &
ORE)
3889 std::string Msg =
"SCoP begins here.";
3890 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"ScopEntry", Beg, P.first)
3897 if (!
scop->hasFeasibleRuntimeContext()) {
3899 Msg =
"SCoP ends here but was dismissed.";
3900 POLLY_DEBUG(dbgs() <<
"SCoP detected but dismissed\n");
3904 Msg =
"SCoP ends here.";
3906 if (
scop->getMaxLoopDepth() > 0)
3910 if (R->isTopLevelRegion())
3911 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"ScopEnd", End, P.first)
3914 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"ScopEnd", End, P.second)
static cl::opt< int > OptComputeOut("polly-dependences-computeout", cl::desc("Bound the dependence analysis by a maximal amount of " "computational steps (0 means no bound)"), cl::Hidden, cl::init(500000), cl::cat(PollyCategory))
llvm::cl::OptionCategory PollyCategory
static cl::opt< int > OptComputeOut("polly-analysis-computeout", cl::desc("Bound the scop analysis by a maximal amount of " "computational steps (0 means no bound)"), cl::Hidden, cl::init(800000), cl::cat(PollyCategory))
static cl::opt< bool > DisableMultiplicativeReductions("polly-disable-multiplicative-reductions", cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::cat(PollyCategory))
static void replaceBasePtrArrays(Scop &S, const ScopArrayInfo *Old, const ScopArrayInfo *New)
Replace the base pointer arrays in all memory accesses referencing Old, with a reference to New.
static std::pair< isl::set, isl::set > partitionSetParts(isl::set S, unsigned Dim)
Compute the (un)bounded parts of S wrt.
static isl::map createNextIterationMap(isl::space SetSpace, unsigned Dim)
}
static isl::set buildConditionSet(ICmpInst::Predicate Pred, isl::pw_aff L, isl::pw_aff R)
Create the conditions under which L Pred R is true.
static const ScopArrayInfo * findCanonicalArray(Scop &S, MemoryAccessList &Accesses)
Find the canonical scop array info object for a set of invariant load hoisted loads.
static isl::set collectBoundedParts(isl::set S)
Add BSet to set BoundedParts if BSet is bounded.
static void joinOrderedPHIs(EquivalenceClasses< Instruction * > &UnionFind, ArrayRef< Instruction * > ModeledInsts)
If the BasicBlock has an edge from itself, ensure that the PHI WRITEs for the incoming values from th...
static cl::opt< std::string > UserContextStr("polly-context", cl::value_desc("isl parameter set"), cl::desc("Provide additional constraints on the context parameters"), cl::init(""), cl::cat(PollyCategory))
static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE)
Check if Expr is divisible by Size.
static BasicBlock * getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx)
Return the idx'th block that is executed after RN.
static cl::opt< bool > PollyAllowDereferenceOfAllFunctionParams("polly-allow-dereference-of-all-function-parameters", cl::desc("Treat all parameters to functions that are pointers as dereferencible." " This is useful for invariant load hoisting, since we can generate" " less runtime checks. This is only valid if all pointers to functions" " are always initialized, so that Polly can choose to hoist" " their loads. "), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
static isl::set getAccessDomain(MemoryAccess *MA)
static cl::opt< unsigned > RunTimeChecksMaxArraysPerGroup("polly-rtc-max-arrays-per-group", cl::desc("The maximal number of arrays to compare in each alias group."), cl::Hidden, cl::init(20), cl::cat(PollyCategory))
static bool isAccessRangeTooComplex(isl::set AccessRange)
Check if an access range is too complex.
static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp)
Return the reduction type for a given binary operator.
static bool isUsedForIndirectHoistedLoad(Scop &S, const ScopArrayInfo *Array)
Check if Array severs as base array in an invariant load.
static cl::opt< bool, true > XModelReadOnlyScalars("polly-analyze-read-only-scalars", cl::desc("Model read-only scalar values in the scop description"), cl::location(ModelReadOnlyScalars), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static bool isAParameter(llvm::Value *maybeParam, const Function &F)
static isl::schedule combineInSequence(isl::schedule Prev, isl::schedule Succ)
static void joinOrderedInstructions(EquivalenceClasses< Instruction * > &UnionFind, ArrayRef< Instruction * > ModeledInsts)
Ensure that the order of ordered instructions does not change.
static cl::opt< unsigned > RunTimeChecksMaxAccessDisjuncts("polly-rtc-max-array-disjuncts", cl::desc("The maximal number of disjunts allowed in memory accesses to " "to build RTCs."), cl::Hidden, cl::init(8), cl::cat(PollyCategory))
static void joinOperandTree(EquivalenceClasses< Instruction * > &UnionFind, ArrayRef< Instruction * > ModeledInsts)
Join instructions to the same statement if one uses the scalar result of the other.
bool hasIntersectingAccesses(isl::set AllAccs, MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::set Domain, SmallVector< MemoryAccess *, 8 > &MemAccs)
True if AllAccs intersects with MemAccs except LoadMA and StoreMA.
static cl::opt< bool > DetectReductions("polly-detect-reductions", cl::desc("Detect and exploit reductions"), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static std::string makeStmtName(BasicBlock *BB, long BBIdx, int Count, bool IsMain, bool IsLast=false)
Generate a name for a statement.
static BasicBlock * getRegionNodeBasicBlock(RegionNode *RN)
Helper to treat non-affine regions and basic blocks the same.
static cl::opt< GranularityChoice > StmtGranularity("polly-stmt-granularity", cl::desc("Algorithm to use for splitting basic blocks into multiple statements"), cl::values(clEnumValN(GranularityChoice::BasicBlocks, "bb", "One statement per basic block"), clEnumValN(GranularityChoice::ScalarIndependence, "scalar-indep", "Scalar independence heuristic"), clEnumValN(GranularityChoice::Stores, "store", "Store-level granularity")), cl::init(GranularityChoice::ScalarIndependence), cl::cat(PollyCategory))
static bool containsErrorBlock(RegionNode *RN, const Region &R, ScopDetection *SD)
static void verifyUse(Scop *S, Use &Op, LoopInfo &LI)
STATISTIC(ScopFound, "Number of valid Scops")
static unsigned const MaxDimensionsInAccessRange
static bool buildMinMaxAccess(isl::set Set, Scop::MinMaxVectorTy &MinMaxAccesses, Scop &S)
Add the minimal/maximal access in Set to User.
static isl::multi_union_pw_aff mapToDimension(isl::union_set USet, unsigned N)
static void verifyUses(Scop *S, LoopInfo &LI, DominatorTree &DT)
Check the consistency of every statement's MemoryAccesses.
static MemoryAccess::ReductionType combineReductionType(MemoryAccess::ReductionType RT0, MemoryAccess::ReductionType RT1)
Combine two reduction types.
static bool isOrderedInstruction(Instruction *Inst)
Is Inst an ordered instruction?
static cl::opt< unsigned > RunTimeChecksMaxParameters("polly-rtc-max-parameters", cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden, cl::init(8), cl::cat(PollyCategory))
static cl::opt< bool > UnprofitableScalarAccs("polly-unprofitable-scalar-accs", cl::desc("Count statements with scalar accesses as not optimizable"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::set Domain, SmallVector< MemoryAccess *, 8 > &MemAccs)
Test if the accesses of LoadMA and StoreMA can form a reduction.
static cl::opt< bool > PollyIgnoreInbounds("polly-ignore-inbounds", cl::desc("Do not take inbounds assumptions at all"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
__isl_null isl_pw_aff * isl_pw_aff_free(__isl_take isl_pw_aff *pwaff)
boolean is_equal(const isl::checked::basic_set &bset2) const
class size domain_tuple_dim() const
isl::checked::set range() const
isl::checked::space get_space() const
isl::checked::map intersect_domain(isl::checked::set set) const
isl::checked::set domain() const
isl::checked::map unite(isl::checked::map map2) const
__isl_give isl_map * copy() const &
__isl_give isl_pw_aff * release()
isl::checked::set gt_set(isl::checked::pw_aff pwaff2) const
isl::checked::set le_set(isl::checked::pw_aff pwaff2) const
isl::checked::multi_pw_aff add(const isl::checked::multi_pw_aff &multi2) const
isl::checked::set eq_set(isl::checked::pw_aff pwaff2) const
isl::checked::set lt_set(isl::checked::pw_aff pwaff2) const
isl::checked::set ne_set(isl::checked::pw_aff pwaff2) const
isl::checked::set ge_set(isl::checked::pw_aff pwaff2) const
isl::checked::pw_aff at(int pos) const
isl::checked::pw_multi_aff coalesce() const
isl::checked::schedule_node child(int pos) const
isl::checked::schedule get_schedule() const
isl::checked::schedule_node insert_mark(isl::checked::id mark) const
isl::checked::schedule_node get_root() const
isl::checked::union_set get_domain() const
boolean is_disjoint(const isl::checked::set &set2) const
class size n_basic_set() const
__isl_give isl_set * copy() const &
isl::checked::set complement() const
isl::checked::set intersect(isl::checked::set set2) const
isl::checked::pw_multi_aff lexmax_pw_multi_aff() const
isl::checked::set gist_params(isl::checked::set context) const
isl::checked::set unite(isl::checked::set set2) const
isl::checked::pw_multi_aff lexmin_pw_multi_aff() const
isl::checked::set detect_equalities() const
boolean is_subset(const isl::checked::set &set2) const
isl::checked::set coalesce() const
class size tuple_dim() const
boolean is_equal(const isl::checked::set &set2) const
isl::checked::space get_space() const
isl::checked::set apply(isl::checked::map map) const
__isl_give isl_set * release()
__isl_keep isl_set * get() const
isl::checked::set subtract(isl::checked::set set2) const
static isl::checked::set empty(isl::checked::space space)
isl::checked::basic_set affine_hull() const
isl::checked::set params() const
isl::checked::set project_out_all_params() const
isl::checked::space params() const
isl::checked::space map_from_set() const
isl::checked::space range() const
isl::checked::union_set range() const
isl::checked::union_map unite(isl::checked::union_map umap2) const
isl::checked::union_map intersect_domain(isl::checked::space space) const
isl::checked::union_map intersect_range(isl::checked::space space) const
isl::checked::set params() const
isl::checked::set_list get_set_list() const
isl::checked::set extract_set(isl::checked::space space) const
isl::checked::space get_space() const
static isl::constraint alloc_inequality(isl::local_space ls)
static isl::constraint alloc_equality(isl::local_space ls)
static isl::id alloc(isl::ctx ctx, const std::string &name, void *user)
static isl::map universe(isl::space space)
static isl::pw_multi_aff project_out_map(isl::space space, isl::dim type, unsigned int first, unsigned int n)
static isl::schedule from_domain(isl::union_set domain)
static isl::set empty(isl::space space)
static isl::set universe(isl::space space)
static isl::union_map empty(isl::ctx ctx)
static isl::union_pw_multi_aff empty(isl::ctx ctx)
Scoped limit of ISL operations.
Utility proxy to wrap the common members of LoadInst and StoreInst.
llvm::Value * getValueOperand() const
static MemAccInst dyn_cast(llvm::Value &V)
llvm::Value * getPointerOperand() const
Represent memory accesses in statements.
void addIncoming(BasicBlock *IncomingBlock, Value *IncomingValue)
Add a new incoming block/value pairs for this PHI/ExitPHI access.
void dump() const
Print the MemoryAccess to stderr.
SmallVector< const SCEV *, 4 > Sizes
Size of each dimension of the accessed array.
AccessType
The access type of a memory access.
ReductionType
Reduction access type.
@ RT_BOTTOM
Pseudo type for the data flow analysis.
@ RT_NONE
Indicate no reduction at all.
bool isValueKind() const
Old name of isOriginalValueKind().
bool isPHIKind() const
Old name of isOriginalPHIKind.
bool isWrite() const
Is this a write memory access?
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
iterator_range< SubscriptsTy::const_iterator > subscripts() const
Return an iterator range containing the subscripts.
bool isExitPHIKind() const
Old name of isOriginalExitPHIKind().
bool isRead() const
Is this a read memory access?
void buildAccessRelation(const ScopArrayInfo *SAI)
Assemble the access relation from all available information.
bool isScalarKind() const
Old name of isOriginalScalarKind.
Type * getElementType() const
Return the element type of the accessed array wrt. this access.
const ScopArrayInfo * getScopArrayInfo() const
Legacy name of getOriginalScopArrayInfo().
Value * getOriginalBaseAddr() const
Get the original base address of this access (e.g.
ScopStmt * getStatement() const
Get the statement that contains this memory access.
bool isAffine() const
Is the memory access affine?
isl::map getAccessRelation() const
Old name of getLatestAccessRelation().
bool isMemoryIntrinsic() const
Is this a memory intrinsic access (memcpy, memset, memmove)?
A class to store information about arrays in the SCoP.
bool isCompatibleWith(const ScopArrayInfo *Array) const
Verify that Array is compatible to this ScopArrayInfo.
isl::id getBasePtrId() const
Return the isl id for the base pointer.
void buildDomain(ScopStmt &Stmt)
Build the domain of Stmt.
void propagateDomainConstraintsToRegionExit(BasicBlock *BB, Loop *BBLoop, SmallPtrSetImpl< BasicBlock * > &FinishedExitBlocks, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Propagate domains that are known due to graph properties.
bool isRequiredInvariantLoad(LoadInst *LI) const
Return true if and only if LI is a required invariant load.
bool propagateInvalidStmtDomains(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Propagate invalid domains of statements through R.
void ensurePHIWrite(PHINode *PHI, ScopStmt *IncomintStmt, BasicBlock *IncomingBlock, Value *IncomingValue, bool IsExitBlock)
Create a write MemoryAccess for the incoming block of a phi node.
void addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs)
Add invariant loads listed in InvMAs with the domain of Stmt.
void canonicalizeDynamicBasePtrs()
Canonicalize arrays with base pointers from the same equivalence class.
bool calculateMinMaxAccess(AliasGroupTy AliasGroup, Scop::MinMaxVectorTy &MinMaxAccesses)
Wrapper function to calculate minimal/maximal accesses to each array.
void verifyInvariantLoads()
Verify that all required invariant loads have been hoisted.
void addUserContext()
Add user provided parameter constraints to context (command line).
void ensureValueRead(Value *V, ScopStmt *UserStmt)
Ensure an llvm::Value is available in the BB's statement, creating a MemoryAccess for reloading it if...
struct LoopStackElement { Loop *L; isl::schedule Schedule; unsigned NumBlocksProcessed; LoopStackElement(Loop *L, isl::schedule S, unsigned NumBlocksProcessed) :L(L), Schedule(S), NumBlocksProcessed(NumBlocksProcessed) {} } LoopStackElementTy
A loop stack element to keep track of per-loop information during schedule construction.
void buildPHIAccesses(ScopStmt *PHIStmt, PHINode *PHI, Region *NonAffineSubRegion, bool IsExitBlock=false)
Create MemoryAccesses for the given PHI node in the given region.
void buildSchedule()
Construct the schedule of this SCoP.
SmallVector< std::pair< ScopStmt *, Instruction * >, 16 > GlobalReads
Set of instructions that might read any memory location.
ScalarEvolution & SE
The ScalarEvolution to help building Scop.
void foldAccessRelations()
Fold memory accesses to handle parametric offset.
std::tuple< AliasGroupVectorTy, DenseSet< const ScopArrayInfo * > > buildAliasGroupsForAccesses()
Build alias groups for all memory accesses in the Scop.
bool propagateDomainConstraints(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Propagate the domain constraints through the region R.
void addPHIReadAccess(ScopStmt *PHIStmt, PHINode *PHI)
Create a MemoryAccess for reading the value of a phi.
bool buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt)
Try to build a MemoryAccess for a call instruction.
void buildScalarDependences(ScopStmt *UserStmt, Instruction *Inst)
Analyze and extract the cross-BB scalar dependences (or, dataflow dependencies) of an instruction.
void foldSizeConstantsToRight()
Fold size constants to the right.
SmallSetVector< Value *, 16 > ArrayBasePointers
Set of all accessed array base pointers.
SmallVector< LoopStackElementTy, 4 > LoopStackTy
The loop stack used for schedule construction.
MemoryAccess * addMemoryAccess(ScopStmt *Stmt, Instruction *Inst, MemoryAccess::AccessType AccType, Value *BaseAddress, Type *ElemType, bool Affine, Value *AccessValue, ArrayRef< const SCEV * > Subscripts, ArrayRef< const SCEV * > Sizes, MemoryKind Kind)
Create a new MemoryAccess object and add it to AccFuncMap.
void hoistInvariantLoads()
Hoist invariant memory loads and check for required ones.
isl::pw_aff getPwAff(BasicBlock *BB, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap, const SCEV *E, bool NonNegative=false, bool IsInsideDomain=true)
Compute the isl representation for the SCEV E in this BB.
SmallVector< AliasGroupTy, 4 > AliasGroupVectorTy
A vector of alias groups.
AAResults & AA
The AAResults to build AliasSetTracker.
bool buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt)
Try to build a multi-dimensional fixed sized MemoryAccess from the Load/Store instruction.
DominatorTree & DT
DominatorTree to reason about guaranteed execution.
const DataLayout & DL
Target data for element size computing.
bool buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt)
Try to build a MemoryAccess for a memory intrinsic.
void assumeNoOutOfBounds()
Assume that all memory accesses are within bounds.
isl::set getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes)
Return the context under which the access cannot be hoisted.
void buildInvariantEquivalenceClasses()
Create equivalence classes for required invariant accesses.
bool buildConditionSets(BasicBlock *BB, Instruction *TI, Loop *L, __isl_keep isl_set *Domain, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap, SmallVectorImpl< __isl_give isl_set * > &ConditionSets, bool IsInsideDomain=true)
Build the conditions sets for the terminator TI in the Domain.
bool buildAliasGroups()
Build all alias groups for this SCoP.
void addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst, MemoryAccess::AccessType AccType, Value *BaseAddress, Type *ElemType, bool IsAffine, ArrayRef< const SCEV * > Subscripts, ArrayRef< const SCEV * > Sizes, Value *AccessValue)
Create a MemoryAccess that represents either a LoadInst or StoreInst.
isl::set adjustDomainDimensions(isl::set Dom, Loop *OldL, Loop *NewL)
Adjust the dimensions of Dom that was constructed for OldL to be compatible to domains constructed fo...
bool buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt)
Try to build a multi-dimensional parametric sized MemoryAccess.
void buildEscapingDependences(Instruction *Inst)
Build the escaping dependences for Inst.
void buildEqivClassBlockStmts(BasicBlock *BB)
Create one or more ScopStmts for BB using equivalence classes.
void splitAliasGroupsByDomain(AliasGroupVectorTy &AliasGroups)
Split alias groups by iteration domains.
bool buildAliasGroup(AliasGroupTy &AliasGroup, DenseSet< const ScopArrayInfo * > HasWriteAccess)
Build a given alias group and its access data.
void addUserAssumptions(AssumptionCache &AC, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Add user provided parameter constraints to context (source code).
void checkForReductions(ScopStmt &Stmt)
Check for reductions in Stmt.
bool buildDomains(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Compute the domain for each basic block in R.
void buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore=false)
Create one or more ScopStmts for BB.
ScopDetection & SD
Valid Regions for Scop.
isl::set buildUnsignedConditionSets(BasicBlock *BB, Value *Condition, const isl::set &Domain, const SCEV *SCEV_TestVal, const SCEV *SCEV_UpperBound, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap, bool IsStrictUpperBound, bool IsInsideDomain=true)
Build condition sets for unsigned ICmpInst(s).
bool shouldModelInst(Instruction *Inst, Loop *L)
Should an instruction be modeled in a ScopStmt.
std::unique_ptr< Scop > scop
void buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt)
Build an instance of MemoryAccess from the Load/Store instruction.
bool buildAliasChecks()
Build the alias checks for this SCoP.
void updateAccessDimensionality()
Update access dimensionalities.
void addRecordedAssumptions()
Add all recorded assumptions to the assumed context.
void buildAccessRelations(ScopStmt &Stmt)
Build the access relation of all memory accesses of Stmt.
RecordedAssumptionsTy RecordedAssumptions
Collection to hold taken assumptions.
bool hasNonHoistableBasePtrInScop(MemoryAccess *MA, isl::union_map Writes)
Check if the base ptr of MA is in the SCoP but not hoistable.
bool addLoopBoundsToHeaderDomain(Loop *L, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Add loop carried constraints to the header block of the loop L.
bool buildDomainsWithBranchConstraints(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Compute the branching constraints for each basic block in R.
void buildAccessFunctions()
Build the access functions for the subregion SR.
bool canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty, bool MAInvalidCtxIsEmpty, bool NonHoistableCtxIsEmpty)
Check if MA can always be hoisted without execution context.
bool buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt)
Build a single-dimensional parametric sized MemoryAccess from the Load/Store instruction.
void collectSurroundingLoops(ScopStmt &Stmt)
Fill NestLoops with loops surrounding Stmt.
void finalizeAccesses()
Finalize all access relations.
void buildScop(Region &R, AssumptionCache &AC)
LoopInfo & LI
LoopInfo for information about loops.
OptimizationRemarkEmitter & ORE
An optimization diagnostic interface to add optimization remarks.
void buildStmts(Region &SR)
Create ScopStmt for all BBs and non-affine subregions of SR.
void ensureValueWrite(Instruction *Inst)
Create a MemoryAccess for writing an llvm::Instruction.
SmallVector< MemoryAccess *, 4 > AliasGroupTy
A vector of memory accesses that belong to an alias group.
isl::set getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain)
Compute the union of predecessor domains for BB.
ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA, const DataLayout &DL, DominatorTree &DT, LoopInfo &LI, ScopDetection &SD, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE)
Pass to detect the maximal static control parts (Scops) of a function.
bool isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R)
Check if the block is a error block.
MemoryAccess & getArrayAccessFor(const Instruction *Inst) const
Return the only array access for Inst.
BasicBlock * getEntryBlock() const
Return a BasicBlock from this statement.
isl::set Domain
The iteration domain describes the set of iterations for which this statement is executed.
const std::vector< Instruction * > & getInstructions() const
bool isBlockStmt() const
Return true if this statement represents a single basic block.
isl::set getInvalidContext() const
Get the invalid context for this statement.
SmallVector< Loop *, 4 > NestLoops
Region * getRegion() const
Get the region represented by this ScopStmt (if any).
bool represents(BasicBlock *BB) const
Return whether this statement represents BB.
BasicBlock * getBasicBlock() const
Get the BasicBlock represented by this ScopStmt (if any).
MemoryAccessVec MemAccs
The memory accesses of this statement.
const char * getBaseName() const
bool contains(const Loop *L) const
Return whether L is boxed within this statement.
void addAccess(MemoryAccess *Access, bool Prepend=false)
Add Access to this statement's list of accesses.
bool isRegionStmt() const
Return true if this statement represents a whole region.
void setInvalidDomain(isl::set ID)
Set the invalid context for this statement to ID.
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
MemoryAccess * lookupValueWriteOf(Instruction *Inst) const
Return the MemoryAccess that writes the value of an instruction defined in this statement,...
Loop * getSurroundingLoop() const
Return the closest innermost loop that contains this statement, but is not contained in it.
MemoryAccess * lookupPHIWriteOf(PHINode *PHI) const
Return the PHI write MemoryAccess for the incoming values from any basic block in this ScopStmt,...
MemoryAccess * lookupValueReadOf(Value *Inst) const
Return the MemoryAccess that reloads a value, or nullptr if not existing, respectively not yet added.
SmallVector< MinMaxAccessTy, 4 > MinMaxVectorTy
Vector of minimal/maximal accesses to different arrays.
static void incrementNumberOfAliasingAssumptions(unsigned Step)
Increment actual number of aliasing assumptions taken.
static std::unique_ptr< Scop > makeScop(Region &R, ScalarEvolution &SE, LoopInfo &LI, DominatorTree &DT, ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE, int ID)
Factory pattern for creating a new (empty) SCoP.
const Region & getRegion() const
Get the maximum region of this static control part.
static VirtualUse create(Scop *S, const Use &U, LoopInfo *LI, bool Virtual)
Get a VirtualUse for an llvm::Use.
enum isl_error isl_ctx_last_error(isl_ctx *ctx)
__isl_null isl_id * isl_id_free(__isl_take isl_id *id)
void * isl_id_get_user(__isl_keep isl_id *id)
boolean manage(isl_bool val)
aff manage_copy(__isl_keep isl_aff *ptr)
std::forward_list< MemoryAccess * > MemoryAccessList
Ordered list type to hold accesses.
std::pair< isl::pw_aff, isl::set > PWACtx
The result type of the SCEVAffinator.
llvm::Loop * getRegionNodeLoop(llvm::RegionNode *RN, llvm::LoopInfo &LI)
Return the smallest loop surrounding RN.
bool isAffineConstraint(llvm::Value *V, const llvm::Region *R, llvm::Loop *Scope, llvm::ScalarEvolution &SE, ParameterSetTy &Params, bool OrExpr=false)
Check if V describes an affine constraint in R.
unsigned const MaxDisjunctsInDomain
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.
void findValues(const llvm::SCEV *Expr, llvm::ScalarEvolution &SE, llvm::SetVector< llvm::Value * > &Values)
Find the values referenced by SCEVUnknowns in a given SCEV expression.
void findLoops(const llvm::SCEV *Expr, llvm::SetVector< const llvm::Loop * > &Loops)
Find the loops referenced from a SCEV expression.
SmallVector< InvariantAccess, 8 > InvariantAccessesTy
Ordered container type to hold invariant accesses.
llvm::SetVector< llvm::AssertingVH< llvm::LoadInst > > InvariantLoadsSetTy
Type for a set of invariant loads.
llvm::SetVector< const llvm::SCEV * > ParameterSetTy
Set type for parameters.
bool isAffineExpr(const llvm::Region *R, llvm::Loop *Scope, const llvm::SCEV *Expression, llvm::ScalarEvolution &SE, InvariantLoadsSetTy *ILS=nullptr)
unsigned getNumBlocksInRegionNode(llvm::RegionNode *RN)
Get the number of blocks in RN.
llvm::Loop * getFirstNonBoxedLoopFor(llvm::Loop *L, llvm::LoopInfo &LI, const BoxedLoopsSetTy &BoxedLoops)
void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End)
Set the begin and end source location for the region limited by P.
AssumptionSign
Enum to distinguish between assumptions and restrictions.
MemoryKind
The different memory kinds used in Polly.
@ 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.
@ ExitPHI
MemoryKind::ExitPHI: Models PHI nodes in the SCoP's exit block.
bool hasDisableAllTransformsHint(llvm::Loop *L)
Does the loop's LoopID contain a 'llvm.loop.disable_heuristics' property?
const llvm::SCEV * tryForwardThroughPHI(const llvm::SCEV *Expr, llvm::Region &R, llvm::ScalarEvolution &SE, ScopDetection *SD)
Try to look through PHI nodes, where some incoming edges come from error blocks.
bool isDebugCall(llvm::Instruction *Inst)
Is the given instruction a call to a debug function?
llvm::iota_range< unsigned > rangeIslSize(unsigned Begin, isl::size End)
Check that End is valid and return an iterator from Begin to End.
void simplify(isl::set &Set)
Simplify a set inplace.
BBPair getBBPairForRegion(const Region *R)
Return the region delimiters (entry & exit block) of R.
llvm::Loop * getLoopSurroundingScop(Scop &S, llvm::LoopInfo &LI)
Get the smallest loop that contains S but is not in S.
void recordAssumption(RecordedAssumptionsTy *RecordedAssumptions, AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc, AssumptionSign Sign, llvm::BasicBlock *BB=nullptr, bool RTC=true)
Record an assumption for later addition to the assumed context.
std::pair< const llvm::SCEVConstant *, const llvm::SCEV * > extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE)
Extract the constant factors from the multiplication M.
bool ModelReadOnlyScalars
Command line switch whether to model read-only accesses.
isl::id createIslLoopAttr(isl::ctx Ctx, llvm::Loop *L)
Create an isl::id that identifies an original loop.
bool PollyUseRuntimeAliasChecks
llvm::Value * getUniqueNonErrorValue(llvm::PHINode *PHI, llvm::Region *R, ScopDetection *SD)
Return a unique non-error block incoming value for PHI if available.
bool PollyInvariantLoadHoisting
bool isIgnoredIntrinsic(const llvm::Value *V)
Return true iff V is an intrinsic that we ignore during code generation.
bool canSynthesize(const llvm::Value *V, const Scop &S, llvm::ScalarEvolution *SE, llvm::Loop *Scope)
Check whether a value an be synthesized by the code generator.
llvm::APInt APIntFromVal(__isl_take isl_val *Val)
Translate isl_val to llvm::APInt.
unsigned getNumBlocksInLoop(llvm::Loop *L)
Get the number of blocks in L.
__isl_export __isl_give isl_set * isl_set_universe(__isl_take isl_space *space)
__isl_export __isl_give isl_set * isl_set_coalesce(__isl_take isl_set *set)
__isl_export __isl_give isl_set * isl_set_subtract(__isl_take isl_set *set1, __isl_take isl_set *set2)
__isl_export __isl_give isl_space * isl_set_get_space(__isl_keep isl_set *set)
__isl_export __isl_give isl_set * isl_set_union(__isl_take isl_set *set1, __isl_take isl_set *set2)
isl_size isl_set_n_param(__isl_keep isl_set *set)
__isl_export __isl_give isl_set * isl_set_complement(__isl_take isl_set *set)
__isl_null isl_set * isl_set_free(__isl_take isl_set *set)
__isl_give isl_set * isl_set_copy(__isl_keep isl_set *set)
__isl_give isl_set * isl_set_project_out(__isl_take isl_set *set, enum isl_dim_type type, unsigned first, unsigned n)
__isl_export isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
__isl_export __isl_give isl_set * isl_set_intersect(__isl_take isl_set *set1, __isl_take isl_set *set2)
__isl_give isl_id * isl_set_get_dim_id(__isl_keep isl_set *set, enum isl_dim_type type, unsigned pos)
__isl_export __isl_give isl_set * isl_set_empty(__isl_take isl_space *space)
__isl_export __isl_give isl_set * isl_set_params(__isl_take isl_set *set)
__isl_give isl_space * isl_space_set_alloc(isl_ctx *ctx, unsigned nparam, unsigned dim)
Helper struct to remember assumptions.
Type for equivalent invariant accesses and their domain context.
MemoryAccessList InvariantAccesses
Memory accesses now treated invariant.
static TupleKindPtr Domain("Domain")