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);
749 SmallVector<BasicBlock *, 4> LatchBlocks;
750 L->getLoopLatches(LatchBlocks);
752 for (BasicBlock *LatchBB : LatchBlocks) {
754 if (!
scop->isDomainDefined(LatchBB))
757 isl::set LatchBBDom =
scop->getDomainConditions(LatchBB);
761 Instruction *TI = LatchBB->getTerminator();
762 if (isa<UncondBrInst>(TI))
763 BackedgeCondition = LatchBBDom;
764 else if (
auto *BI = dyn_cast<CondBrInst>(TI)) {
765 SmallVector<isl_set *, 8> ConditionSets;
766 int idx = BI->getSuccessor(0) != HeaderBB;
768 InvalidDomainMap, ConditionSets,
775 BackedgeCondition =
isl::manage(ConditionSets[idx]);
777 llvm_unreachable(
"Only branch instructions allowed in loop latches");
779 int LatchLoopDepth =
scop->getRelativeLoopDepth(
LI.getLoopFor(LatchBB));
780 assert(LatchLoopDepth >= LoopDepth);
781 BackedgeCondition = BackedgeCondition.project_out(
783 UnionBackedgeCondition = UnionBackedgeCondition.
unite(BackedgeCondition);
787 for (
int i = 0; i < LoopDepth; i++)
790 isl::set UnionBackedgeConditionComplement =
792 UnionBackedgeConditionComplement =
793 UnionBackedgeConditionComplement.lower_bound_si(
isl::dim::set, LoopDepth,
795 UnionBackedgeConditionComplement =
796 UnionBackedgeConditionComplement.
apply(ForwardMap);
797 HeaderBBDom = HeaderBBDom.
subtract(UnionBackedgeConditionComplement);
798 HeaderBBDom = HeaderBBDom.
apply(NextIterationMap);
801 HeaderBBDom = Parts.second;
806 bool RequiresRTC = !
scop->hasNSWAddRecForLoop(L);
811 nullptr, RequiresRTC);
816 DenseMap<std::pair<const SCEV *, Type *>, LoadInst *> EquivClasses;
819 for (LoadInst *LInst : RIL) {
820 const SCEV *PointerSCEV =
SE.getSCEV(LInst->getPointerOperand());
822 Type *Ty = LInst->getType();
823 LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)];
825 scop->addInvariantLoadMapping(LInst, ClassRep);
830 scop->addInvariantEquivClass(
836 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
837 bool IsOnlyNonAffineRegion =
scop->isNonAffineSubRegion(R);
838 auto *EntryBB = R->getEntry();
839 auto *L = IsOnlyNonAffineRegion ? nullptr :
LI.getLoopFor(EntryBB);
840 int LD =
scop->getRelativeLoopDepth(L);
848 if (IsOnlyNonAffineRegion)
876 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
888 SmallPtrSet<BasicBlock *, 8> FinishedExitBlocks;
889 ReversePostOrderTraversal<Region *> RTraversal(R);
890 for (
auto *RN : RTraversal) {
893 if (RN->isSubRegion()) {
894 Region *SubRegion = RN->getNodeAs<Region>();
895 if (!
scop->isNonAffineSubRegion(SubRegion)) {
903 scop->notifyErrorBlock();
907 Instruction *TI = BB->getTerminator();
909 if (isa<UnreachableInst>(TI))
912 if (!
scop->isDomainDefined(BB))
929 auto IsFinishedRegionExit = [&FinishedExitBlocks](BasicBlock *SuccBB) {
930 return FinishedExitBlocks.count(SuccBB);
932 if (std::all_of(succ_begin(BB), succ_end(BB), IsFinishedRegionExit))
939 SmallVector<isl_set *, 8> ConditionSets;
940 if (RN->isSubRegion())
941 ConditionSets.push_back(
Domain.copy());
943 ConditionSets,
false))
950 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
951 for (
unsigned u = 0, e = ConditionSets.size(); u < e; u++) {
956 if (!
scop->contains(SuccBB))
961 if (FinishedExitBlocks.count(SuccBB))
965 if (
DT.dominates(SuccBB, BB))
976 isl::set &SuccDomain =
scop->getOrInitEmptyDomain(SuccBB);
983 SuccDomain = CondSet;
994 while (++u < ConditionSets.size())
1004 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1005 ReversePostOrderTraversal<Region *> RTraversal(R);
1006 for (
auto *RN : RTraversal) {
1010 if (RN->isSubRegion()) {
1011 Region *SubRegion = RN->getNodeAs<Region>();
1012 if (!
scop->isNonAffineSubRegion(SubRegion)) {
1021 assert(!
Domain.is_null() &&
"Cannot propagate a nullptr");
1023 isl::set InvalidDomain = InvalidDomainMap[BB];
1025 bool IsInvalidBlock = ContainsErrorBlock ||
Domain.is_subset(InvalidDomain);
1027 if (!IsInvalidBlock) {
1038 InvalidDomainMap[BB] = InvalidDomain;
1043 auto *TI = BB->getTerminator();
1044 unsigned NumSuccs = RN->isSubRegion() ? 1 : TI->getNumSuccessors();
1045 for (
unsigned u = 0; u < NumSuccs; u++) {
1049 if (!
scop->contains(SuccBB))
1053 if (
DT.dominates(SuccBB, BB))
1059 auto AdjustedInvalidDomain =
1062 isl::set SuccInvalidDomain = InvalidDomainMap[SuccBB];
1063 SuccInvalidDomain = SuccInvalidDomain.
unite(AdjustedInvalidDomain);
1064 SuccInvalidDomain = SuccInvalidDomain.
coalesce();
1066 InvalidDomainMap[SuccBB] = SuccInvalidDomain;
1074 InvalidDomainMap.erase(BB);
1075 scop->invalidate(
COMPLEXITY, TI->getDebugLoc(), TI->getParent());
1079 InvalidDomainMap[BB] = InvalidDomain;
1086 Region *NonAffineSubRegion,
1096 auto *Scope =
LI.getLoopFor(
PHI->getParent());
1103 bool OnlyNonAffineSubRegionOperands =
true;
1104 for (
unsigned u = 0; u <
PHI->getNumIncomingValues(); u++) {
1105 Value *Op =
PHI->getIncomingValue(u);
1106 BasicBlock *OpBB =
PHI->getIncomingBlock(u);
1111 if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB)) {
1112 auto *OpInst = dyn_cast<Instruction>(Op);
1113 if (!OpInst || !NonAffineSubRegion->contains(OpInst))
1118 OnlyNonAffineSubRegionOperands =
false;
1122 if (!OnlyNonAffineSubRegionOperands && !IsExitBlock) {
1128 Instruction *Inst) {
1129 assert(!isa<PHINode>(Inst));
1132 for (Use &Op : Inst->operands())
1145 return Prev.sequence(Succ);
1176 Result = Result.add_pw_multi_aff(PMA);
1186 assert(LoopStack.size() == 1 && LoopStack.back().L == L);
1187 scop->setScheduleTree(LoopStack[0].Schedule);
1217 ReversePostOrderTraversal<Region *> RTraversal(R);
1218 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end());
1219 std::deque<RegionNode *> DelayList;
1220 bool LastRNWaiting =
false;
1229 while (!WorkList.empty() || !DelayList.empty()) {
1232 if ((LastRNWaiting && !WorkList.empty()) || DelayList.empty()) {
1233 RN = WorkList.front();
1234 WorkList.pop_front();
1235 LastRNWaiting =
false;
1237 RN = DelayList.front();
1238 DelayList.pop_front();
1242 if (!
scop->contains(L))
1245 Loop *LastLoop = LoopStack.back().L;
1246 if (LastLoop != L) {
1247 if (LastLoop && !LastLoop->contains(L)) {
1248 LastRNWaiting =
true;
1249 DelayList.push_back(RN);
1252 LoopStack.push_back({L, {}, 0});
1259 if (RN->isSubRegion()) {
1260 auto *LocalRegion = RN->getNodeAs<Region>();
1261 if (!
scop->isNonAffineSubRegion(LocalRegion)) {
1267 assert(LoopStack.rbegin() != LoopStack.rend());
1268 auto LoopData = LoopStack.rbegin();
1271 for (
auto *Stmt :
scop->getStmtListFor(RN)) {
1286 size_t Dimension = LoopStack.size();
1287 while (LoopData->L &&
1290 auto NumBlocksProcessed = LoopData->NumBlocksProcessed;
1292 assert(std::next(LoopData) != LoopStack.rend());
1293 Loop *L = LoopData->L;
1300 Schedule = Schedule.insert_partial_schedule(MUPA);
1309 scop->markDisableHeuristics();
1321 LoopData->NumBlocksProcessed += NumBlocksProcessed;
1324 LoopStack.erase(LoopStack.begin() + Dimension, LoopStack.end());
1331 if (
scop->isEscaping(Inst))
1342 if (AS.BB && !AS.Set.is_params()) {
1358 S = std::move(
S).intersect(std::move(Dom));
1360 S = std::move(Dom).subtract(std::move(
S));
1391 S.get_space().universe_set().intersect_params(PSet);
1393 "Must not overapproximate assumptions/restructions");
1397 scop->addAssumption(AS.Kind, std::move(PSet), AS.Loc, Sign, AS.BB,
1403 AssumptionCache &AC, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1405 auto *CI = dyn_cast_or_null<CallInst>(
Assumption);
1406 if (!CI || CI->arg_size() != 1)
1409 bool InScop =
scop->contains(CI);
1410 if (!InScop && !
scop->isDominatedBy(
DT, CI->getParent()))
1413 auto *L =
LI.getLoopFor(CI->getParent());
1414 auto *Val = CI->getArgOperand(0);
1416 auto &R =
scop->getRegion();
1419 OptimizationRemarkAnalysis(
DEBUG_TYPE,
"IgnoreUserAssumption", CI)
1420 <<
"Non-affine user assumption ignored.");
1426 for (
auto *Param : DetectedParams) {
1428 Param =
scop->getRepresentingInvariantLoadSCEV(Param);
1429 if (
scop->isParam(Param))
1431 NewParams.insert(Param);
1435 SmallVector<isl_set *, 2> ConditionSets;
1436 auto *TI = InScop ? CI->getParent()->getTerminator() :
nullptr;
1437 BasicBlock *BB = InScop ? CI->getParent() : R.getEntry();
1440 assert(Dom &&
"Cannot propagate a nullptr.");
1448 isl_set *AssumptionCtx =
nullptr;
1458 if (!NewParams.empty()) {
1464 if (!NewParams.count(Param))
1471 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"UserAssumption", CI)
1472 <<
"Use user assumption: "
1473 << stringFromIslObj(AssumptionCtx,
"null"));
1483 scop->setContext(newContext);
1496 Type *ElementType = Val->getType();
1498 const SCEV *AccessFunction =
1499 SE.getSCEVAtScope(Address,
LI.getLoopFor(Inst->getParent()));
1500 const SCEVUnknown *BasePointer =
1501 dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1505 if (
auto *BitCast = dyn_cast<BitCastInst>(Address))
1506 Address = BitCast->getOperand(0);
1508 auto *GEP = dyn_cast<GetElementPtrInst>(Address);
1509 if (!GEP ||
DL.getTypeAllocSize(GEP->getResultElementType()) !=
1510 DL.getTypeAllocSize(ElementType))
1513 SmallVector<const SCEV *, 4> Subscripts;
1514 SmallVector<const SCEV *, 4> Sizes;
1515 getIndexExpressionsFromGEP(
SE, GEP, Subscripts, Sizes);
1516 auto *BasePtr = GEP->getOperand(0);
1518 if (
auto *BasePtrCast = dyn_cast<BitCastInst>(BasePtr))
1519 BasePtr = BasePtrCast->getOperand(0);
1523 if (BasePtr != BasePointer->getValue())
1529 for (
auto *Subscript : Subscripts) {
1535 for (LoadInst *LInst : AccessILS)
1536 if (!ScopRIL.count(LInst))
1543 std::vector<const SCEV *> SizesSCEV;
1544 SizesSCEV.push_back(
nullptr);
1545 SizesSCEV.insert(SizesSCEV.end(), Sizes.begin(), Sizes.end());
1547 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1548 true, Subscripts, SizesSCEV, Val);
1562 Type *ElementType = Val->getType();
1563 unsigned ElementSize =
DL.getTypeAllocSize(ElementType);
1567 const SCEV *AccessFunction =
1568 SE.getSCEVAtScope(Address,
LI.getLoopFor(Inst->getParent()));
1569 const SCEVUnknown *BasePointer =
1570 dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1572 assert(BasePointer &&
"Could not find base pointer");
1574 auto &InsnToMemAcc =
scop->getInsnToMemAccMap();
1575 auto AccItr = InsnToMemAcc.find(Inst);
1576 if (AccItr == InsnToMemAcc.end())
1579 std::vector<const SCEV *> Sizes = {
nullptr};
1581 Sizes.insert(Sizes.end(), AccItr->second.Shape->DelinearizedSizes.begin(),
1582 AccItr->second.Shape->DelinearizedSizes.end());
1587 if (Sizes.size() == 1)
1596 auto DelinearizedSize =
1597 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue();
1599 if (ElementSize != DelinearizedSize)
1602 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1603 true, AccItr->second.DelinearizedSubscripts, Sizes, Val);
1608 auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst);
1610 if (MemIntr ==
nullptr)
1613 auto *L =
LI.getLoopFor(Inst->getParent());
1614 const SCEV *LengthVal =
SE.getSCEVAtScope(MemIntr->getLength(), L);
1623 LengthVal,
SE, &AccessILS);
1624 for (LoadInst *LInst : AccessILS)
1625 if (!ScopRIL.count(LInst))
1626 LengthIsAffine =
false;
1627 if (!LengthIsAffine)
1628 LengthVal =
nullptr;
1630 auto *DestPtrVal = MemIntr->getDest();
1633 const SCEV *DestAccFunc =
SE.getSCEVAtScope(DestPtrVal, L);
1640 if (DestAccFunc->isZero())
1643 if (
auto *U = dyn_cast<SCEVUnknown>(DestAccFunc)) {
1644 if (isa<ConstantPointerNull>(U->getValue()))
1648 auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(
SE.getPointerBase(DestAccFunc));
1650 DestAccFunc =
SE.getMinusSCEV(DestAccFunc, DestPtrSCEV);
1652 IntegerType::getInt8Ty(DestPtrVal->getContext()),
1653 LengthIsAffine, {DestAccFunc, LengthVal}, {nullptr},
1656 auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr);
1660 auto *SrcPtrVal = MemTrans->getSource();
1663 const SCEV *SrcAccFunc =
SE.getSCEVAtScope(SrcPtrVal, L);
1667 if (SrcAccFunc->isZero())
1670 auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(
SE.getPointerBase(SrcAccFunc));
1672 SrcAccFunc =
SE.getMinusSCEV(SrcAccFunc, SrcPtrSCEV);
1674 IntegerType::getInt8Ty(SrcPtrVal->getContext()),
1675 LengthIsAffine, {SrcAccFunc, LengthVal}, {nullptr},
1682 auto *CI = dyn_cast_or_null<CallInst>(Inst);
1690 const SCEV *AF =
SE.getConstant(IntegerType::getInt64Ty(CI->getContext()), 0);
1691 auto *CalledFunction = CI->getCalledFunction();
1692 MemoryEffects ME =
AA.getMemoryEffects(CalledFunction);
1693 if (ME.doesNotAccessMemory())
1696 if (ME.onlyAccessesArgPointees()) {
1697 ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
1700 Loop *L =
LI.getLoopFor(Inst->getParent());
1701 for (
const auto &Arg : CI->args()) {
1702 if (!Arg->getType()->isPointerTy())
1705 const SCEV *ArgSCEV =
SE.getSCEVAtScope(Arg, L);
1706 if (ArgSCEV->isZero())
1709 if (
auto *U = dyn_cast<SCEVUnknown>(ArgSCEV)) {
1710 if (isa<ConstantPointerNull>(U->getValue()))
1714 auto *ArgBasePtr = cast<SCEVUnknown>(
SE.getPointerBase(ArgSCEV));
1716 ArgBasePtr->getType(),
false, {AF}, {nullptr}, CI);
1721 if (ME.onlyReadsMemory()) {
1735 Type *ElementType = Val->getType();
1739 const SCEV *AccessFunction =
1740 SE.getSCEVAtScope(Address,
LI.getLoopFor(Inst->getParent()));
1741 const SCEVUnknown *BasePointer =
1742 dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1744 assert(BasePointer &&
"Could not find base pointer");
1745 AccessFunction =
SE.getMinusSCEV(AccessFunction, BasePointer);
1748 bool isVariantInNonAffineLoop =
false;
1749 SetVector<const Loop *> Loops;
1751 for (
const Loop *L : Loops)
1753 isVariantInNonAffineLoop =
true;
1760 bool IsAffine = !isVariantInNonAffineLoop &&
1762 AccessFunction,
SE, &AccessILS);
1765 for (LoadInst *LInst : AccessILS)
1766 if (!ScopRIL.count(LInst))
1772 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1773 IsAffine, {AccessFunction}, {nullptr}, Val);
1794 "At least one of the buildAccess functions must handled this access, or "
1795 "ScopDetection should have rejected this SCoP");
1799 for (
auto &Stmt : *
scop) {
1800 if (Stmt.isBlockStmt()) {
1805 Region *R = Stmt.getRegion();
1806 for (BasicBlock *BB : R->blocks())
1814 for (BasicBlock *BB :
scop->getRegion().blocks()) {
1815 for (Instruction &Inst : *BB)
1834 bool IsMain,
bool IsLast =
false) {
1841 else if (Count < 26)
1842 Suffix +=
'a' + Count;
1844 Suffix += std::to_string(Count);
1859 Loop *SurroundingLoop =
LI.getLoopFor(BB);
1862 long BBIdx =
scop->getNextStmtIdx();
1863 std::vector<Instruction *> Instructions;
1864 for (Instruction &Inst : *BB) {
1866 Instructions.push_back(&Inst);
1867 if (Inst.getMetadata(
"polly_split_after") ||
1868 (SplitOnStore && isa<StoreInst>(Inst))) {
1869 std::string Name =
makeStmtName(BB, BBIdx, Count, Count == 0);
1870 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1872 Instructions.clear();
1876 std::string Name =
makeStmtName(BB, BBIdx, Count, Count == 0);
1877 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1886 return Inst->mayHaveSideEffects() || Inst->mayReadOrWriteMemory();
1892 ArrayRef<Instruction *> ModeledInsts) {
1893 for (Instruction *Inst : ModeledInsts) {
1894 if (isa<PHINode>(Inst))
1897 for (Use &Op : Inst->operands()) {
1898 Instruction *OpInst = dyn_cast<Instruction>(Op.get());
1903 if (!UnionFind.contains(OpInst))
1906 UnionFind.unionSets(Inst, OpInst);
1918 ArrayRef<Instruction *> ModeledInsts) {
1919 SetVector<Instruction *> SeenLeaders;
1920 for (Instruction *Inst : ModeledInsts) {
1924 Instruction *Leader = UnionFind.getLeaderValue(Inst);
1929 bool Inserted = SeenLeaders.insert(Leader);
1937 for (Instruction *Prev : reverse(SeenLeaders)) {
1945 UnionFind.unionSets(Prev, Leader);
1969 ArrayRef<Instruction *> ModeledInsts) {
1970 for (Instruction *Inst : ModeledInsts) {
1971 PHINode *
PHI = dyn_cast<PHINode>(Inst);
1975 int Idx =
PHI->getBasicBlockIndex(
PHI->getParent());
1979 Instruction *IncomingVal =
1980 dyn_cast<Instruction>(
PHI->getIncomingValue(Idx));
1984 UnionFind.unionSets(
PHI, IncomingVal);
1989 Loop *L =
LI.getLoopFor(BB);
1993 SmallVector<Instruction *, 32> ModeledInsts;
1994 EquivalenceClasses<Instruction *> UnionFind;
1995 Instruction *MainInst =
nullptr, *MainLeader =
nullptr;
1996 for (Instruction &Inst : *BB) {
1999 ModeledInsts.push_back(&Inst);
2000 UnionFind.insert(&Inst);
2007 if (!MainInst && (isa<StoreInst>(Inst) ||
2008 (isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst))))
2018 MapVector<Instruction *, std::vector<Instruction *>> LeaderToInstList;
2023 for (Instruction *Inst : ModeledInsts) {
2027 auto LeaderIt = UnionFind.findLeader(Inst);
2028 if (LeaderIt == UnionFind.member_end())
2032 (void)LeaderToInstList[*LeaderIt];
2037 for (Instruction *Inst : ModeledInsts) {
2038 auto LeaderIt = UnionFind.findLeader(Inst);
2039 if (LeaderIt == UnionFind.member_end())
2042 if (Inst == MainInst)
2043 MainLeader = *LeaderIt;
2044 std::vector<Instruction *> &InstList = LeaderToInstList[*LeaderIt];
2045 InstList.push_back(Inst);
2050 long BBIdx =
scop->getNextStmtIdx();
2051 for (
auto &Instructions : LeaderToInstList) {
2052 std::vector<Instruction *> &InstList = Instructions.second;
2055 bool IsMain = (MainInst ? MainLeader == Instructions.first : Count == 0);
2057 std::string Name =
makeStmtName(BB, BBIdx, Count, IsMain);
2058 scop->addScopStmt(BB, Name, L, std::move(InstList));
2068 std::string EpilogueName =
makeStmtName(BB, BBIdx, Count, Count == 0,
true);
2069 scop->addScopStmt(BB, EpilogueName, L, {});
2073 if (
scop->isNonAffineSubRegion(&SR)) {
2074 std::vector<Instruction *> Instructions;
2075 Loop *SurroundingLoop =
2077 for (Instruction &Inst : *SR.getEntry())
2079 Instructions.push_back(&Inst);
2080 long RIdx =
scop->getNextStmtIdx();
2082 scop->addScopStmt(&SR, Name, SurroundingLoop, Instructions);
2086 for (
auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
2087 if (I->isSubRegion())
2090 BasicBlock *BB = I->getNodeAs<BasicBlock>();
2106 Region *NonAffineSubRegion) {
2109 "The exit BB is the only one that cannot be represented by a statement");
2114 if (
SD.isErrorBlock(BB,
scop->getRegion()))
2117 auto BuildAccessesForInst = [
this, Stmt,
2118 NonAffineSubRegion](Instruction *Inst) {
2119 PHINode *
PHI = dyn_cast<PHINode>(Inst);
2124 assert(Stmt &&
"Cannot build access function in non-existing statement");
2140 BuildAccessesForInst(Inst);
2142 BuildAccessesForInst(BB.getTerminator());
2144 for (Instruction &Inst : BB) {
2149 if (isa<LoadInst>(Inst) && RIL.count(cast<LoadInst>(&Inst)))
2152 BuildAccessesForInst(&Inst);
2159 Value *BaseAddress, Type *ElementType,
bool Affine,
Value *AccessValue,
2160 ArrayRef<const SCEV *> Subscripts, ArrayRef<const SCEV *> Sizes,
2162 bool isKnownMustAccess =
false;
2166 isKnownMustAccess =
true;
2174 if (Inst &&
DT.dominates(Inst->getParent(), Stmt->
getRegion()->getExit()))
2175 isKnownMustAccess =
true;
2182 isKnownMustAccess =
true;
2187 auto *Access =
new MemoryAccess(Stmt, Inst, AccType, BaseAddress, ElementType,
2188 Affine, Subscripts, Sizes, AccessValue,
Kind);
2190 scop->addAccessFunction(Access);
2197 Value *BaseAddress, Type *ElementType,
2199 ArrayRef<const SCEV *> Subscripts,
2200 ArrayRef<const SCEV *> Sizes,
2201 Value *AccessValue) {
2208static bool isDivisible(
const SCEV *Expr,
unsigned Size, ScalarEvolution &SE) {
2214 if (
auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
2215 for (
const SCEV *FactorExpr : MulExpr->operands())
2223 if (
auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
2224 for (
const SCEV *OpExpr : NAryExpr->operands())
2230 const SCEV *SizeSCEV = SE.getConstant(Expr->getType(), Size);
2231 const SCEV *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV);
2232 const SCEV *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV);
2233 return MulSCEV == Expr;
2240 if (
Array->getNumberOfDimensions() <= 1)
2244 Space = Space.align_params(Accessed.
get_space());
2246 if (!Accessed.contains(Space))
2252 std::vector<int> Int;
2254 for (
unsigned i = 0; i < Dims; i++) {
2256 DimOnly = DimOnly.project_out(
isl::dim::set, 1, Dims - i - 1);
2261 if (i == Dims - 1) {
2268 isl::aff Diff = DimHull.get_div(0);
2269 isl::val Val = Diff.get_denominator_val();
2274 if (ValAPInt.isSignedIntN(32))
2275 ValInt = ValAPInt.getSExtValue();
2279 Int.push_back(ValInt);
2284 Transform = Transform.add_constraint(
C);
2296 Int.push_back(ValInt);
2301 if (!Elements.
is_subset(MappedElements))
2304 bool CanFold =
true;
2308 unsigned NumDims =
Array->getNumberOfDimensions();
2309 for (
unsigned i = 1; i < NumDims - 1; i++)
2310 if (Int[0] != Int[i] && Int[i])
2316 for (
auto &Access :
scop->access_functions())
2317 if (Access->getScopArrayInfo() ==
Array)
2318 Access->setAccessRelation(
2319 Access->getAccessRelation().apply_range(Transform));
2321 std::vector<const SCEV *> Sizes;
2322 for (
unsigned i = 0; i < NumDims; i++) {
2323 auto Size =
Array->getDimensionSize(i);
2325 if (i == NumDims - 1)
2326 Size =
SE.getMulExpr(Size,
SE.getConstant(Size->getType(), Int[0]));
2327 Sizes.push_back(Size);
2330 Array->updateSizes(Sizes,
false );
2346 if (!Access->isArrayKind())
2351 if (
Array->getNumberOfDimensions() != 1)
2353 unsigned DivisibleSize =
Array->getElemSizeInBytes();
2354 const SCEV *Subscript = Access->getSubscript(0);
2357 auto *Ty = IntegerType::get(
SE.getContext(), DivisibleSize * 8);
2358 Array->updateElementType(Ty);
2361 for (
auto &Stmt : *
scop)
2362 for (
auto &Access : Stmt)
2363 Access->updateDimensionality();
2367 for (
auto &Stmt : *
scop)
2368 for (
auto &Access : Stmt)
2369 Access->foldAccessRelation();
2375 for (
auto &Stmt : *
scop)
2376 for (
auto &Access : Stmt) {
2377 isl::set Outside = Access->assumeNoOutOfBound();
2378 const auto &Loc = Access->getAccessInstruction()
2379 ? Access->getAccessInstruction()->getDebugLoc()
2397 Stmt =
scop->getLastStmtFor(Inst->getParent());
2408 true, Inst, ArrayRef<const SCEV *>(),
2424 switch (VUse.getKind()) {
2447 true, V, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2458 BasicBlock *IncomingBlock,
2459 Value *IncomingValue,
bool IsExitBlock) {
2464 scop->getOrCreateScopArrayInfo(
PHI,
PHI->getType(), {},
2481 assert(Acc->getAccessInstruction() ==
PHI);
2482 Acc->addIncoming(IncomingBlock, IncomingValue);
2488 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2496 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2503 Stmt.
Domain =
scop->getDomainConditions(&Stmt);
2511 Loop *L =
LI.getLoopFor(BB);
2514 L = L->getParentLoop();
2516 SmallVector<llvm::Loop *, 8> Loops;
2520 L = L->getParentLoop();
2531 switch (BinOp->getOpcode()) {
2532 case Instruction::FAdd:
2533 if (!BinOp->isFast())
2536 case Instruction::Add:
2538 case Instruction::Or:
2540 case Instruction::Xor:
2542 case Instruction::And:
2544 case Instruction::FMul:
2545 if (!BinOp->isFast())
2548 case Instruction::Mul:
2572 SmallVector<MemoryAccess *, 8> &MemAccs) {
2573 bool HasIntersectingAccs =
false;
2577 if (MA == LoadMA || MA == StoreMA)
2579 auto AccRel = MA->getAccessRelation().intersect_domain(
Domain);
2580 auto Accs = AccRel.range();
2581 auto AccsNoParams = Accs.project_out_all_params();
2583 bool CompatibleSpace = AllAccsNoParams.has_equal_space(AccsNoParams);
2585 if (CompatibleSpace) {
2586 auto OverlapAccs = Accs.intersect(AllAccs);
2587 bool DoesIntersect = !OverlapAccs.is_empty();
2588 HasIntersectingAccs |= DoesIntersect;
2591 return HasIntersectingAccs;
2597 SmallVector<MemoryAccess *, 8> &MemAccs) {
2601 bool Valid = LoadAccs.has_equal_space(StoreAccs);
2602 POLLY_DEBUG(dbgs() <<
" == The accessed space below is "
2603 << (Valid ?
"" :
"not ") <<
"equal!\n");
2618 POLLY_DEBUG(dbgs() <<
" == The accessed memory is " << (Valid ?
"" :
"not ")
2619 <<
"overlapping!\n");
2628 POLLY_DEBUG(dbgs() <<
" == The accessed memory is " << (Valid ?
"not " :
"")
2629 <<
"accessed by other instructions!\n");
2643 using StatePairTy = std::pair<unsigned, MemoryAccess::ReductionType>;
2644 using FlowInSetTy = MapVector<const LoadInst *, StatePairTy>;
2645 using StateTy = MapVector<const Instruction *, FlowInSetTy>;
2657 SmallPtrSet<const Instruction *, 8> InvalidLoads;
2658 SmallVector<BasicBlock *, 8> ScopBlocks;
2661 ScopBlocks.push_back(BB);
2663 for (BasicBlock *Block : Stmt.
getRegion()->blocks())
2664 ScopBlocks.push_back(Block);
2666 for (BasicBlock *Block : ScopBlocks) {
2667 for (Instruction &Inst : *Block) {
2668 if ((Stmt.
getParent())->getStmtFor(&Inst) != &Stmt)
2670 bool UsedOutsideStmt = any_of(Inst.users(), [&Stmt](User *U) {
2671 return (Stmt.getParent())->getStmtFor(cast<Instruction>(U)) != &Stmt;
2674 if (
auto *Load = dyn_cast<LoadInst>(&Inst)) {
2676 if (
auto *Ptr = dyn_cast<Instruction>(Load->getPointerOperand())) {
2677 const auto &It = State.find(Ptr);
2678 if (It != State.end())
2679 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2683 if (UsedOutsideStmt)
2684 InvalidLoads.insert(Load);
2693 if (
auto *Store = dyn_cast<StoreInst>(&Inst)) {
2695 if (
const Instruction *Ptr =
2696 dyn_cast<Instruction>(Store->getPointerOperand())) {
2697 const auto &It = State.find(Ptr);
2698 if (It != State.end())
2699 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2703 if (
auto *ValueInst = dyn_cast<Instruction>(Store->getValueOperand()))
2704 State.insert(std::make_pair(Store, State[ValueInst]));
2710 auto *BinOp = dyn_cast<BinaryOperator>(&Inst);
2712 POLLY_DEBUG(dbgs() <<
"CurInst: " << Inst <<
" RT: " << CurRedType
2717 FlowInSetTy &InstInFlowSet = State[&Inst];
2718 for (Use &Op : Inst.operands()) {
2719 auto *OpInst = dyn_cast<Instruction>(Op);
2723 POLLY_DEBUG(dbgs().indent(4) <<
"Op Inst: " << *OpInst <<
"\n");
2724 const StateTy::iterator &OpInFlowSetIt = State.find(OpInst);
2725 if (OpInFlowSetIt == State.end())
2730 FlowInSetTy &OpInFlowSet = OpInFlowSetIt->second;
2731 for (
auto &OpInFlowPair : OpInFlowSet) {
2732 unsigned OpFlowIn = OpInFlowPair.second.first;
2733 unsigned InstFlowIn = InstInFlowSet[OpInFlowPair.first].first;
2737 InstInFlowSet[OpInFlowPair.first].second;
2744 POLLY_DEBUG(dbgs().indent(8) <<
"OpRedType: " << OpRedType <<
"\n");
2745 POLLY_DEBUG(dbgs().indent(8) <<
"NewRedType: " << NewRedType <<
"\n");
2746 InstInFlowSet[OpInFlowPair.first] =
2747 std::make_pair(OpFlowIn + InstFlowIn, NewRedType);
2753 if (UsedOutsideStmt)
2754 InvalidLoads.insert_range(llvm::make_first_range(InstInFlowSet));
2763 using MemAccPair = std::pair<MemoryAccess *, MemoryAccess *>;
2764 DenseMap<MemAccPair, MemoryAccess::ReductionType> ValidCandidates;
2774 assert(!St->isVolatile());
2777 for (
auto &MaInFlowSetElem : MaInFlowSet) {
2779 assert(ReadMA &&
"Couldn't find memory access for incoming load!");
2782 <<
"'\n\tflows into\n'"
2784 << MaInFlowSetElem.second.first <<
" times & RT: "
2785 << MaInFlowSetElem.second.second <<
"\n");
2788 unsigned NumAllowableInFlow = 1;
2791 bool Valid = (MaInFlowSetElem.second.first == NumAllowableInFlow);
2803 ValidCandidates[std::make_pair(ReadMA, WriteMA)] = RT;
2811 for (
auto &CandidatePair : ValidCandidates) {
2816 dbgs() <<
" Load :: "
2817 << *((CandidatePair.first.first)->getAccessInstruction())
2819 << *((CandidatePair.first.second)->getAccessInstruction())
2820 <<
"\n are marked as reduction like\n");
2822 CandidatePair.first.first->markAsReductionLike(RT);
2823 CandidatePair.first.second->markAsReductionLike(RT);
2828 auto &RIL =
scop->getRequiredInvariantLoads();
2829 for (LoadInst *
LI : RIL) {
2834 if (Stmt.getArrayAccessOrNULLFor(
LI)) {
2852 InvariantAccesses.push_back({Access, NHCtx});
2856 for (
auto InvMA : InvariantAccesses)
2857 Stmt.removeMemoryAccess(InvMA.MA);
2875 unsigned NumTotalDims = 0;
2890 if (
auto *BasePtrMA =
scop->lookupBasePtrAccess(MA)) {
2895 if (
auto *BasePtrInst = dyn_cast<Instruction>(BaseAddr))
2896 if (!isa<LoadInst>(BasePtrInst))
2897 return scop->contains(BasePtrInst);
2911 std::string SpaceStr = stringFromIslObj(Space,
"null");
2912 errs() <<
"Error: the context provided in -polly-context has not the same "
2913 <<
"number of dimensions than the computed context. Due to this "
2914 <<
"mismatch, the -polly-context option is ignored. Please provide "
2915 <<
"the context in the parameter space: " << SpaceStr <<
".\n";
2920 std::string NameContext =
2922 std::string NameUserContext = UserContext.get_dim_name(
isl::dim::param, i);
2924 if (NameContext != NameUserContext) {
2925 std::string SpaceStr = stringFromIslObj(Space,
"null");
2926 errs() <<
"Error: the name of dimension " << i
2927 <<
" provided in -polly-context "
2928 <<
"is '" << NameUserContext <<
"', but the name in the computed "
2929 <<
"context is '" << NameContext
2930 <<
"'. Due to this name mismatch, "
2931 <<
"the -polly-context option is ignored. Please provide "
2932 <<
"the context in the parameter space: " << SpaceStr <<
".\n";
2939 isl::set newContext =
scop->getContext().intersect(UserContext);
2940 scop->setContext(newContext);
2974 if (AccessRelation.involves_dims(
isl::dim::in, 0, Stmt.getNumIterators()))
2980 auto &
DL =
scop->getFunction().getDataLayout();
2981 if (isSafeToLoadUnconditionally(
LI->getPointerOperand(),
LI->getType(),
2982 LI->getAlign(),
DL,
nullptr)) {
2984 }
else if (BB !=
LI->getParent()) {
2989 SafeToLoad = AccessRelation.
range();
2997 bool IsWritten = !WrittenCtx.
is_empty();
3002 WrittenCtx = WrittenCtx.remove_divs();
3014 for (
const llvm::Argument &Arg : F.args())
3015 if (&Arg == maybeParam)
3022 bool StmtInvalidCtxIsEmpty,
3023 bool MAInvalidCtxIsEmpty,
3024 bool NonHoistableCtxIsEmpty) {
3026 const DataLayout &
DL = LInst->getDataLayout();
3033 if (!isDereferenceableAndAlignedPointer(
3034 LInst->getPointerOperand(), LInst->getType(), LInst->getAlign(),
DL))
3040 if (!NonHoistableCtxIsEmpty)
3045 if (StmtInvalidCtxIsEmpty && MAInvalidCtxIsEmpty)
3051 for (
const SCEV *Subscript : MA->
subscripts())
3052 if (!isa<SCEVConstant>(Subscript))
3063 bool StmtInvalidCtxIsEmpty = StmtInvalidCtx.
is_empty();
3068 DomainCtx = DomainCtx.
subtract(StmtInvalidCtx);
3071 auto *AccInst = InvMAs.front().MA->getAccessInstruction();
3072 scop->invalidate(
COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent());
3081 for (
auto &InvMA : InvMAs) {
3082 auto *MA = InvMA.MA;
3083 Instruction *AccInst = MA->getAccessInstruction();
3084 if (
SE.isSCEVable(AccInst->getType())) {
3085 SetVector<Value *> Values;
3086 for (
const SCEV *Parameter :
scop->parameters()) {
3089 if (!Values.count(AccInst))
3102 for (
auto &InvMA : InvMAs) {
3103 auto *MA = InvMA.MA;
3104 isl::set NHCtx = InvMA.NonHoistableCtx;
3109 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
3110 Type *Ty = LInst->getType();
3111 const SCEV *PointerSCEV =
SE.getSCEV(LInst->getPointerOperand());
3113 isl::set MAInvalidCtx = MA->getInvalidContext();
3114 bool NonHoistableCtxIsEmpty = NHCtx.
is_empty();
3115 bool MAInvalidCtxIsEmpty = MAInvalidCtx.
is_empty();
3120 NonHoistableCtxIsEmpty)) {
3128 bool Consolidated =
false;
3129 for (
auto &IAClass :
scop->invariantEquivClasses()) {
3130 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
3138 auto &MAs = IAClass.InvariantAccesses;
3140 auto *LastMA = MAs.front();
3142 isl::set AR = MA->getAccessRelation().range();
3143 isl::set LastAR = LastMA->getAccessRelation().range();
3153 Consolidated =
true;
3156 isl::set IAClassDomainCtx = IAClass.ExecutionContext;
3157 if (!IAClassDomainCtx.
is_null())
3158 IAClassDomainCtx = IAClassDomainCtx.
unite(MACtx).
coalesce();
3160 IAClassDomainCtx = MACtx;
3161 IAClass.ExecutionContext = IAClassDomainCtx;
3172 scop->addInvariantEquivClass(
3187 return CanonicalArray;
3195 for (
MemoryAccess *Access2 : EqClass2.InvariantAccesses)
3207 if (Access->getLatestScopArrayInfo() != Old)
3211 isl::map Map = Access->getAccessRelation();
3213 Access->setAccessRelation(Map);
3224 if (!CanonicalBasePtrSAI)
3230 if (!BasePtrSAI || BasePtrSAI == CanonicalBasePtrSAI ||
3264 for (
const SCEV *Size : Access->
Sizes) {
3270 ElementType, Access->
Sizes, Ty);
3275 for (
const SCEV *Subscript : Access->
subscripts()) {
3276 if (!Access->
isAffine() || !Subscript)
3282 scop->addAccessData(Access);
3297 Set = Set.remove_divs();
3304 Set = Set.simple_hull();
3322 unsigned InvolvedParams = 0;
3346 assert(MaxOutputSize >= 1 &&
"Assumed at least one output dimension");
3348 Pos = MaxOutputSize - 1;
3349 LastDimAff = MaxPMA.
at(Pos);
3351 OneAff = OneAff.add_constant_si(1);
3352 LastDimAff = LastDimAff.
add(OneAff);
3353 MaxPMA = MaxPMA.set_pw_aff(Pos, LastDimAff);
3358 MinMaxAccesses.push_back(std::make_pair(MinPMA, MaxPMA));
3366 MinMaxAccesses.reserve(AliasGroup.size());
3372 Accesses = Accesses.
unite(MA->getAccessRelation());
3377 bool LimitReached =
false;
3384 return !LimitReached;
3391 return Domain.reset_tuple_id();
3401 if (
scop->getAliasGroups().size())
3411 POLLY_DEBUG(dbgs() <<
"\n\nNOTE: Run time checks for " <<
scop->getNameStr()
3412 <<
" could not be created. This SCoP has been dismissed.");
3416std::tuple<ScopBuilder::AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>>
3418 BatchAAResults BAA(
AA);
3419 AliasSetTracker AST(BAA);
3421 DenseMap<Value *, MemoryAccess *> PtrToAcc;
3422 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3425 isl::set StmtDomain = Stmt.getDomain();
3426 bool StmtDomainEmpty = StmtDomain.
is_empty();
3429 if (StmtDomainEmpty)
3433 if (MA->isScalarKind())
3436 HasWriteAccess.insert(MA->getScopArrayInfo());
3438 if (MA->isRead() && isa<MemTransferInst>(Acc))
3439 PtrToAcc[cast<MemTransferInst>(Acc)->getRawSource()] = MA;
3447 for (AliasSet &AS : AST) {
3448 if (AS.isMustAlias() || AS.isForwardingAliasSet())
3451 for (
const Value *Ptr : AS.getPointers())
3452 AG.push_back(PtrToAcc[
const_cast<Value *
>(Ptr)]);
3455 AliasGroups.push_back(std::move(AG));
3458 return std::make_tuple(AliasGroups, HasWriteAccess);
3468 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3475 if (!
scop->hasFeasibleRuntimeContext())
3494 AliasGroupTy &AliasGroup, DenseSet<const ScopArrayInfo *> HasWriteAccess) {
3497 SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays;
3498 SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays;
3500 if (AliasGroup.size() < 2)
3504 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"PossibleAlias",
3505 Access->getAccessInstruction())
3506 <<
"Possibly aliasing pointer, use restrict keyword.");
3508 if (HasWriteAccess.count(
Array)) {
3509 ReadWriteArrays.insert(
Array);
3510 ReadWriteAccesses.push_back(Access);
3512 ReadOnlyArrays.insert(
Array);
3513 ReadOnlyAccesses.push_back(Access);
3519 if (ReadOnlyAccesses.empty() && ReadWriteArrays.size() <= 1)
3523 if (ReadWriteArrays.empty())
3529 if (!MA->isAffine()) {
3530 scop->invalidate(
ALIASING, MA->getAccessInstruction()->getDebugLoc(),
3531 MA->getAccessInstruction()->getParent());
3540 scop->addRequiredInvariantLoad(
3541 cast<LoadInst>(BasePtrMA->getAccessInstruction()));
3559 if (MinMaxAccessesReadWrite.size() + ReadOnlyArrays.size() >
3565 scop->addAliasGroup(MinMaxAccessesReadWrite, MinMaxAccessesReadOnly);
3573 for (
unsigned u = 0; u < AliasGroups.size(); u++) {
3576 AliasGroupTy::iterator AGI = AG.begin();
3578 while (AGI != AG.end()) {
3582 NewAG.push_back(MA);
3583 AGI = AG.erase(AGI);
3585 AGDomain = AGDomain.
unite(MADomain);
3589 if (NewAG.size() > 1)
3590 AliasGroups.push_back(std::move(NewAG));
3598 assert(PhysUse.getKind() == VirtUse.getKind());
3617 for (
auto *BB :
S->getRegion().blocks()) {
3618 for (
auto &Inst : *BB) {
3619 auto *Stmt =
S->getStmtFor(&Inst);
3627 if (Inst.isTerminator() && Stmt->isBlockStmt())
3631 for (
auto &Op : Inst.operands())
3635 if (isa<StoreInst>(Inst))
3650 if (
S->hasSingleExitEdge())
3654 if (!
S->getRegion().isTopLevelRegion()) {
3655 for (
auto &Inst : *
S->getRegion().getExit()) {
3656 if (!isa<PHINode>(Inst))
3659 for (
auto &Op : Inst.operands())
3676 for (BasicBlock *BB :
scop->getRegion().blocks()) {
3677 if (
SD.isErrorBlock(*BB,
scop->getRegion()))
3680 for (Instruction &Inst : *BB) {
3681 LoadInst *Load = dyn_cast<LoadInst>(&Inst);
3685 if (!RIL.count(Load))
3692 ArrayRef<ScopStmt *> List =
scop->getStmtListFor(BB);
3707 if (!R.isTopLevelRegion() && !
scop->hasSingleExitEdge()) {
3708 for (Instruction &Inst : *R.getExit()) {
3709 PHINode *
PHI = dyn_cast<PHINode>(&Inst);
3718 const SCEV *AF =
SE.getConstant(IntegerType::getInt64Ty(
SE.getContext()), 0);
3720 ScopStmt *GlobalReadStmt = GlobalReadPair.first;
3721 Instruction *GlobalRead = GlobalReadPair.second;
3724 BP, BP->getType(),
false, {AF}, {nullptr}, GlobalRead);
3730 DenseMap<BasicBlock *, isl::set> InvalidDomainMap;
3734 dbgs() <<
"Bailing-out because buildDomains encountered problems\n");
3750 scop->removeStmtNotInDomainMap();
3751 scop->simplifySCoP(
false);
3752 if (
scop->isEmpty()) {
3753 POLLY_DEBUG(dbgs() <<
"Bailing-out because SCoP is empty\n");
3769 if (!
scop->hasFeasibleRuntimeContext()) {
3771 dbgs() <<
"Bailing-out because of unfeasible context (early)\n");
3780 dbgs() <<
"Bailing-out because SCoP is not considered profitable\n");
3788 scop->realignParams();
3796 scop->simplifyContexts();
3798 POLLY_DEBUG(dbgs() <<
"Bailing-out because could not build alias checks\n");
3805 scop->simplifySCoP(
true);
3809 if (!
scop->hasFeasibleRuntimeContext()) {
3810 POLLY_DEBUG(dbgs() <<
"Bailing-out because of unfeasible context (late)\n");
3820 const DataLayout &
DL, DominatorTree &
DT, LoopInfo &
LI,
3822 OptimizationRemarkEmitter &
ORE)
3828 std::string Msg =
"SCoP begins here.";
3829 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"ScopEntry", Beg, P.first)
3836 if (!
scop->hasFeasibleRuntimeContext()) {
3838 Msg =
"SCoP ends here but was dismissed.";
3839 POLLY_DEBUG(dbgs() <<
"SCoP detected but dismissed\n");
3843 Msg =
"SCoP ends here.";
3845 if (
scop->getMaxLoopDepth() > 0)
3849 if (R->isTopLevelRegion())
3850 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"ScopEnd", End, P.first)
3853 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 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")