52#include "llvm/ADT/SmallPtrSet.h"
53#include "llvm/ADT/Statistic.h"
54#include "llvm/Analysis/AliasAnalysis.h"
55#include "llvm/Analysis/Delinearization.h"
56#include "llvm/Analysis/Loads.h"
57#include "llvm/Analysis/LoopInfo.h"
58#include "llvm/Analysis/OptimizationRemarkEmitter.h"
59#include "llvm/Analysis/RegionInfo.h"
60#include "llvm/Analysis/ScalarEvolution.h"
61#include "llvm/Analysis/ScalarEvolutionExpressions.h"
62#include "llvm/IR/BasicBlock.h"
63#include "llvm/IR/DebugLoc.h"
64#include "llvm/IR/DerivedTypes.h"
65#include "llvm/IR/DiagnosticInfo.h"
66#include "llvm/IR/DiagnosticPrinter.h"
67#include "llvm/IR/Dominators.h"
68#include "llvm/IR/Function.h"
69#include "llvm/IR/InstrTypes.h"
70#include "llvm/IR/Instruction.h"
71#include "llvm/IR/Instructions.h"
72#include "llvm/IR/IntrinsicInst.h"
73#include "llvm/IR/Metadata.h"
74#include "llvm/IR/Module.h"
75#include "llvm/IR/Value.h"
76#include "llvm/Support/Debug.h"
77#include "llvm/Support/Regex.h"
78#include "llvm/Support/raw_ostream.h"
91#define DEBUG_TYPE "polly-detect"
98 "polly-detect-profitability-min-per-loop-insts",
99 cl::desc(
"The minimal number of per-loop instructions before a single loop "
100 "region is considered profitable"),
101 cl::Hidden, cl::ValueRequired, cl::init(100000000), cl::cat(
PollyCategory));
106 "polly-process-unprofitable",
108 "Process scops that are unlikely to benefit from Polly optimizations."),
113 cl::desc(
"Only run on functions that match a regex. "
114 "Multiple regexes can be comma separated. "
115 "Scop detection will run on all functions that match "
116 "ANY of the regexes provided."),
121 cl::desc(
"Ignore functions that match a regex. "
122 "Multiple regexes can be comma separated. "
123 "Scop detection will ignore all functions that match "
124 "ANY of the regexes provided."),
129static cl::opt<bool, true>
131 cl::desc(
"Allow the detection of full functions"),
137 cl::desc(
"Only run on certain regions (The provided identifier must "
138 "appear in the name of the region's entry block"),
139 cl::value_desc(
"identifier"), cl::ValueRequired, cl::init(
""),
144 cl::desc(
"Ignore possible aliasing of the array bases"),
150 "polly-allow-unsigned-operations",
151 cl::desc(
"Allow unsigned operations such as comparisons or zero-extends."),
158 "polly-use-runtime-alias-checks",
159 cl::desc(
"Use runtime alias checks to resolve possible aliasing."),
165 cl::desc(
"Print information about the activities of Polly"),
169 "polly-allow-differing-element-types",
170 cl::desc(
"Allow different element types for array accesses"), cl::Hidden,
175 cl::desc(
"Allow non affine access functions in arrays"),
180 cl::desc(
"Allow functions with known modref behavior"),
184 "polly-allow-nonaffine-branches",
185 cl::desc(
"Allow non affine conditions for branches"), cl::Hidden,
190 cl::desc(
"Allow non affine conditions for loops"),
193static cl::opt<bool, true>
195 cl::desc(
"Track failure strings in detecting scop regions"),
199static cl::opt<bool>
KeepGoing(
"polly-detect-keep-going",
200 cl::desc(
"Do not fail on the first error."),
203static cl::opt<bool, true>
205 cl::desc(
"Delinearize array access functions"),
211 cl::desc(
"Verify the detected SCoPs after each transformation"),
216static cl::opt<bool, true>
218 cl::desc(
"Hoist invariant loads."),
223 "polly-allow-error-blocks",
224 cl::desc(
"Allow to speculate on the execution of 'error blocks'."),
239STATISTIC(NumScopsDepthZero,
"Number of scops with maximal loop depth 0");
240STATISTIC(NumScopsDepthOne,
"Number of scops with maximal loop depth 1");
241STATISTIC(NumScopsDepthTwo,
"Number of scops with maximal loop depth 2");
242STATISTIC(NumScopsDepthThree,
"Number of scops with maximal loop depth 3");
243STATISTIC(NumScopsDepthFour,
"Number of scops with maximal loop depth 4");
244STATISTIC(NumScopsDepthFive,
"Number of scops with maximal loop depth 5");
246 "Number of scops with maximal loop depth 6 and larger");
247STATISTIC(NumProfScopRegions,
"Number of scops (profitable scops only)");
249 "Number of loops in scops (profitable scops only)");
252 "Number of scops with maximal loop depth 0 (profitable scops only)");
254 "Number of scops with maximal loop depth 1 (profitable scops only)");
256 "Number of scops with maximal loop depth 2 (profitable scops only)");
258 "Number of scops with maximal loop depth 3 (profitable scops only)");
260 "Number of scops with maximal loop depth 4 (profitable scops only)");
262 "Number of scops with maximal loop depth 5 (profitable scops only)");
264 "Number of scops with maximal loop depth 6 and larger "
265 "(profitable scops only)");
266STATISTIC(MaxNumLoopsInScop,
"Maximal number of loops in scops");
268 "Maximal number of loops in scops (profitable scops only)");
271 bool OnlyProfitable);
275class DiagnosticScopFound final :
public DiagnosticInfo {
277 static int PluginDiagnosticKind;
280 std::string FileName;
281 unsigned EntryLine, ExitLine;
284 DiagnosticScopFound(Function &F, std::string FileName,
unsigned EntryLine,
286 : DiagnosticInfo(PluginDiagnosticKind, DS_Note), F(F), FileName(FileName),
287 EntryLine(EntryLine), ExitLine(ExitLine) {}
289 void print(DiagnosticPrinter &DP)
const override;
291 static bool classof(
const DiagnosticInfo *DI) {
292 return DI->getKind() == PluginDiagnosticKind;
297int DiagnosticScopFound::PluginDiagnosticKind =
298 getNextAvailablePluginDiagnosticKind();
300void DiagnosticScopFound::print(DiagnosticPrinter &DP)
const {
301 DP <<
"Polly detected an optimizable loop region (scop) in function '" << F
304 if (FileName.empty()) {
305 DP <<
"Scop location is unknown. Compile with debug info "
306 "(-g) to get more precise information. ";
310 DP << FileName <<
":" << EntryLine <<
": Start of scop\n";
311 DP << FileName <<
":" << ExitLine <<
": End of scop";
318 const cl::list<std::string> &RegexList) {
319 for (
auto RegexStr : RegexList) {
324 report_fatal_error(Twine(
"invalid regex given as input to polly: ") + Err,
337 LoopInfo &
LI, RegionInfo &
RI, AAResults &
AA,
338 OptimizationRemarkEmitter &
ORE)
347 Region *TopRegion =
RI.getTopLevelRegion();
391 "Cached more results than valid regions");
394template <
class RR,
typename... Args>
396 Args &&...Arguments)
const {
399 std::shared_ptr<RR>
RejectReason = std::make_shared<RR>(Arguments...);
409 assert(!Assert &&
"Verification of detected scop failed");
427 Entry = std::make_unique<DetectionContext>(
const_cast<Region &
>(R),
AA,
443 if (!Log || !Log->hasErrors())
447 return RR->getMessage();
459 for (BasicBlock *BB : AR->blocks()) {
460 Loop *L =
LI.getLoopFor(BB);
471 const DataLayout &DL = CurRegion.getEntry()->getModule()->getDataLayout();
476 for (LoadInst *Load : RequiredILS) {
488 if (isSafeToLoadUnconditionally(Load->getPointerOperand(),
489 Load->getType(), Load->getAlign(), DL,
493 if (NonAffineRegion->contains(Load) &&
494 Load->getParent() != NonAffineRegion->getEntry())
506 SetVector<Value *> Values;
511 SmallPtrSet<Value *, 8> PtrVals;
512 for (
auto *V : Values) {
513 if (
auto *P2I = dyn_cast<PtrToIntInst>(V))
514 V = P2I->getOperand(0);
516 if (!V->getType()->isPointerTy())
519 const SCEV *PtrSCEV =
SE.getSCEVAtScope(V, Scope);
520 if (isa<SCEVConstant>(PtrSCEV))
523 auto *BasePtr = dyn_cast<SCEVUnknown>(
SE.getPointerBase(PtrSCEV));
527 Value *BasePtrVal = BasePtr->getValue();
528 if (PtrVals.insert(BasePtrVal).second) {
529 for (
auto *PtrVal : PtrVals)
530 if (PtrVal != BasePtrVal && !
AA.isNoAlias(PtrVal, BasePtrVal))
551 Value *Condition,
bool IsLoopBranch,
553 Loop *L =
LI.getLoopFor(&BB);
554 const SCEV *ConditionSCEV =
SE.getSCEVAtScope(Condition, L);
556 if (IsLoopBranch && L->isLoopLatch(&BB))
563 if (
isAffine(ConditionSCEV, L, Context))
571 ConditionSCEV, ConditionSCEV, SI);
575 Value *Condition,
bool IsLoopBranch,
578 if (isa<ConstantInt>(Condition))
581 if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
582 auto Opcode = BinOp->getOpcode();
583 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
584 Value *Op0 = BinOp->getOperand(0);
585 Value *Op1 = BinOp->getOperand(1);
591 if (
auto PHI = dyn_cast<PHINode>(Condition)) {
592 auto *Unique = dyn_cast_or_null<ConstantInt>(
594 if (Unique && (Unique->isZero() || Unique->isOne()))
598 if (
auto Load = dyn_cast<LoadInst>(Condition))
599 if (!IsLoopBranch && Context.
CurRegion.contains(Load)) {
605 if (!isa<ICmpInst>(Condition)) {
612 ICmpInst *ICmp = cast<ICmpInst>(Condition);
615 if (isa<UndefValue>(ICmp->getOperand(0)) ||
616 isa<UndefValue>(ICmp->getOperand(1)))
619 Loop *L =
LI.getLoopFor(&BB);
620 const SCEV *LHS =
SE.getSCEVAtScope(ICmp->getOperand(0), L);
621 const SCEV *RHS =
SE.getSCEVAtScope(ICmp->getOperand(1), L);
655 bool AllowUnreachable,
659 Instruction *TI = BB.getTerminator();
661 if (AllowUnreachable && isa<UnreachableInst>(TI))
665 if (isa<ReturnInst>(TI) && CurRegion.isTopLevelRegion())
668 if (isa<UncondBrInst>(TI))
671 if (
auto *BI = dyn_cast<CondBrInst>(TI)) {
672 Value *Condition = BI->getCondition();
673 if (isa<UndefValue>(Condition))
675 return isValidBranch(BB, BI, Condition, IsLoopBranch, Context);
678 if (
auto *SI = dyn_cast<SwitchInst>(TI)) {
679 Value *Condition = SI->getCondition();
680 if (isa<UndefValue>(Condition))
682 return isValidSwitch(BB, SI, Condition, IsLoopBranch, Context);
690 if (CI.doesNotReturn())
693 if (CI.doesNotAccessMemory())
696 if (
auto *II = dyn_cast<IntrinsicInst>(&CI))
700 Function *CalledFunction = CI.getCalledFunction();
703 if (CalledFunction ==
nullptr)
707 POLLY_DEBUG(dbgs() <<
"Allow call to debug function: "
708 << CalledFunction->getName() <<
'\n');
713 MemoryEffects ME =
AA.getMemoryEffects(CalledFunction);
714 if (ME.onlyAccessesArgPointees()) {
715 for (
const auto &Arg : CI.args()) {
716 if (!Arg->getType()->isPointerTy())
721 const SCEV *ArgSCEV =
722 SE.getSCEVAtScope(Arg,
LI.getLoopFor(CI.getParent()));
723 if (ArgSCEV->isZero())
726 auto *BP = dyn_cast<SCEVUnknown>(
SE.getPointerBase(ArgSCEV));
737 Context.
AST.addUnknown(&CI);
741 if (ME.onlyReadsMemory()) {
747 Context.
AST.addUnknown(&CI);
762 Loop *L =
LI.getLoopFor(II.getParent());
766 const SCEVUnknown *BP;
768 switch (II.getIntrinsicID()) {
770 case Intrinsic::memmove:
771 case Intrinsic::memcpy:
772 AF =
SE.getSCEVAtScope(cast<MemTransferInst>(II).getSource(), L);
774 BP = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AF));
780 case Intrinsic::memset:
781 AF =
SE.getSCEVAtScope(cast<MemIntrinsic>(II).getDest(), L);
783 BP = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AF));
790 if (!
isAffine(
SE.getSCEVAtScope(cast<MemIntrinsic>(II).getLength(), L), L,
805 if (isa<Argument>(Val) || isa<Constant>(Val))
808 Instruction *I = dyn_cast<Instruction>(&Val);
812 if (!Reg.contains(I))
818 if (
auto LI = dyn_cast<LoadInst>(I)) {
819 Ctx.RequiredILS.insert(
LI);
840class SCEVRemoveMax final :
public SCEVRewriteVisitor<SCEVRemoveMax> {
842 SCEVRemoveMax(ScalarEvolution &SE, std::vector<const SCEV *> *Terms)
843 : SCEVRewriteVisitor(SE), Terms(Terms) {}
845 static const SCEV *rewrite(
const SCEV *Scev, ScalarEvolution &SE,
846 std::vector<const SCEV *> *Terms =
nullptr) {
847 SCEVRemoveMax Rewriter(SE, Terms);
848 return Rewriter.visit(Scev);
851 const SCEV *visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
852 if ((Expr->getNumOperands() == 2) && Expr->getOperand(0)->isZero()) {
853 auto Res = visit(Expr->getOperand(1));
855 (*Terms).push_back(
Res);
863 std::vector<const SCEV *> *Terms;
867SmallVector<const SCEV *, 4>
869 const SCEVUnknown *BasePointer)
const {
870 SmallVector<const SCEV *, 4> Terms;
871 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
872 std::vector<const SCEV *> MaxTerms;
873 SCEVRemoveMax::rewrite(
Pair.second,
SE, &MaxTerms);
874 if (!MaxTerms.empty()) {
875 for (
const SCEV *Max : MaxTerms)
877 SE.getTruncateOrSignExtend(Max,
Pair.second->getType()));
888 if (
auto *AF = dyn_cast<SCEVAddExpr>(
Pair.second)) {
889 for (
auto Op : AF->operands()) {
890 if (
auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
891 collectParametricTerms(
SE, AF2, Terms);
892 if (
auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
893 SmallVector<SCEVUse, 0> Operands;
895 for (
const SCEV *MulOp : AF2->operands()) {
896 if (
auto *Const = dyn_cast<SCEVConstant>(MulOp))
897 Operands.push_back(Const);
898 if (
auto *Unknown = dyn_cast<SCEVUnknown>(MulOp)) {
899 if (
auto *Inst = dyn_cast<Instruction>(Unknown->getValue())) {
901 Operands.push_back(MulOp);
904 Operands.push_back(MulOp);
909 Terms.push_back(
SE.getMulExpr(Operands));
914 collectParametricTerms(
SE,
Pair.second, Terms);
920 SmallVectorImpl<const SCEV *> &Sizes,
921 const SCEVUnknown *BasePointer,
929 if (Sizes.size() == 0)
932 Value *BaseValue = BasePointer->getValue();
934 for (
const SCEV *DelinearizedSize : Sizes) {
937 if (!
isAffine(DelinearizedSize,
nullptr, Context)) {
941 if (
auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
942 auto *V = dyn_cast<Value>(Unknown->getValue());
943 if (
auto *Load = dyn_cast<LoadInst>(V)) {
953 Context,
true, DelinearizedSize,
954 Context.
Accesses[BasePointer].front().first, BaseValue);
962 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
963 const Instruction *Insn =
Pair.first;
964 const SCEV *AF =
Pair.second;
966 if (!
isAffine(AF, Scope, Context)) {
986 std::shared_ptr<ArrayShape> Shape)
const {
987 Value *BaseValue = BasePointer->getValue();
988 bool BasePtrHasNonAffine =
false;
990 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
991 const Instruction *Insn =
Pair.first;
992 auto *AF =
Pair.second;
993 AF = SCEVRemoveMax::rewrite(AF,
SE);
994 bool IsNonAffine =
false;
995 TempMemoryAccesses.insert(std::make_pair(Insn,
MemAcc(Insn, Shape)));
996 MemAcc *Acc = &TempMemoryAccesses.find(Insn)->second;
997 auto *Scope =
LI.getLoopFor(Insn->getParent());
1005 if (Shape->DelinearizedSizes.size() == 0) {
1009 Shape->DelinearizedSizes);
1020 BasePtrHasNonAffine =
true;
1030 if (!BasePtrHasNonAffine)
1031 Context.
InsnToMemAcc.insert(TempMemoryAccesses.begin(),
1032 TempMemoryAccesses.end());
1038 const SCEVUnknown *BasePointer,
1039 Loop *Scope)
const {
1040 auto Shape = std::shared_ptr<ArrayShape>(
new ArrayShape(BasePointer));
1044 findArrayDimensions(
SE, Terms, Shape->DelinearizedSizes,
1061 auto *BasePointer =
Pair.first;
1062 auto *Scope =
Pair.second;
1073 const SCEVUnknown *BP,
1079 auto *BV = BP->getValue();
1080 if (isa<UndefValue>(BV))
1084 if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BV))
1092 AF =
SE.getMinusSCEV(AF, BP);
1095 if (!isa<MemIntrinsic>(Inst)) {
1096 Size =
SE.getElementSize(Inst);
1099 SE.getEffectiveSCEVType(PointerType::getUnqual(
SE.getContext()));
1100 Size =
SE.getConstant(SizeTy, 8);
1113 bool IsVariantInNonAffineLoop =
false;
1114 SetVector<const Loop *> Loops;
1116 for (
const Loop *L : Loops)
1118 IsVariantInNonAffineLoop =
true;
1120 auto *Scope =
LI.getLoopFor(Inst->getParent());
1121 bool IsAffine = !IsVariantInNonAffineLoop &&
isAffine(AF, Scope, Context);
1123 if (isa<MemIntrinsic>(Inst) && !IsAffine) {
1127 Context.
Accesses[BP].push_back({Inst, AF});
1131 std::make_pair(BP,
LI.getLoopFor(Inst->getParent())));
1142 AAMDNodes AATags = Inst->getAAMetadata();
1143 AliasSet &AS = Context.
AST.getAliasSetFor(
1144 MemoryLocation::getBeforeOrAfter(BP->getValue(), AATags));
1146 if (!AS.isMustAlias()) {
1148 bool CanBuildRunTimeCheck =
true;
1155 auto ASPointers = AS.getPointers();
1163 const unsigned int VariantSize = VariantLS.size(),
1164 InvariantSize = InvariantLS.size();
1166 for (
const Value *Ptr : ASPointers) {
1167 Instruction *Inst = dyn_cast<Instruction>(
const_cast<Value *
>(Ptr));
1168 if (Inst && Context.
CurRegion.contains(Inst)) {
1169 auto *Load = dyn_cast<LoadInst>(Inst);
1170 if (Load && InvariantLS.count(Load))
1174 if (VariantLS.count(Load))
1175 VariantLS.remove(Load);
1177 InvariantLS.insert(Load);
1179 CanBuildRunTimeCheck =
false;
1180 VariantLS.insert(Load);
1185 if (InvariantSize == InvariantLS.size() &&
1186 VariantSize == VariantLS.size())
1190 if (CanBuildRunTimeCheck)
1202 Loop *L =
LI.getLoopFor(Inst->getParent());
1203 const SCEV *AccessFunction =
SE.getSCEVAtScope(Ptr, L);
1204 const SCEVUnknown *BasePointer;
1206 BasePointer = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1208 return isValidAccess(Inst, AccessFunction, BasePointer, Context);
1216 if (isa<ScalableVectorType>(Ty))
1224 for (
auto &Op : Inst.operands()) {
1225 auto *OpInst = dyn_cast<Instruction>(&Op);
1234 auto *
PHI = dyn_cast<PHINode>(OpInst);
1236 for (User *U :
PHI->users()) {
1237 auto *UI = dyn_cast<Instruction>(U);
1238 if (!UI || !UI->isTerminator())
1247 if (isa<LandingPadInst>(&Inst) || isa<ResumeInst>(&Inst))
1254 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1261 if (!Inst.mayReadOrWriteMemory()) {
1262 if (!isa<AllocaInst>(Inst))
1270 Context.
hasStores |= isa<StoreInst>(MemInst);
1271 Context.
hasLoads |= isa<LoadInst>(MemInst);
1272 if (!MemInst.isSimple())
1289 SmallVector<BasicBlock *, 4> ExitingBlocks;
1290 L->getExitingBlocks(ExitingBlocks);
1291 return !ExitingBlocks.empty();
1306 SmallVector<BasicBlock *, 4> LoopControlBlocks;
1307 L->getExitingBlocks(LoopControlBlocks);
1308 L->getLoopLatches(LoopControlBlocks);
1309 for (BasicBlock *ControlBB : LoopControlBlocks) {
1310 if (!
isValidCFG(*ControlBB,
true,
false, Context)) {
1358 SmallVector<BasicBlock *, 4> ExitBlocks;
1359 L->getExitBlocks(ExitBlocks);
1360 BasicBlock *TheExitBlock = ExitBlocks[0];
1361 for (BasicBlock *ExitBB : ExitBlocks) {
1362 if (TheExitBlock != ExitBB)
1370 Region *R =
RI.getRegionFor(L->getHeader());
1371 while (R != &Context.
CurRegion && !R->contains(L))
1378 const SCEV *LoopCount =
SE.getBackedgeTakenCount(L);
1386 unsigned MinProfitableTrips) {
1387 const SCEV *TripCount =
SE.getBackedgeTakenCount(L);
1390 int MaxLoopDepth = 1;
1391 if (MinProfitableTrips > 0)
1392 if (
auto *TripCountC = dyn_cast<SCEVConstant>(TripCount))
1393 if (TripCountC->getType()->getScalarSizeInBits() <= 64)
1394 if (TripCountC->getValue()->getZExtValue() <= MinProfitableTrips)
1397 for (
auto &SubLoop : *L) {
1400 MaxLoopDepth = std::max(MaxLoopDepth, Stats.
MaxDepth + 1);
1403 return {NumLoops, MaxLoopDepth};
1408 LoopInfo &
LI,
unsigned MinProfitableTrips) {
1410 int MaxLoopDepth = 0;
1412 auto L =
LI.getLoopFor(R->getEntry());
1416 if (L && R->contains(L)) {
1417 L = R->outermostLoopInRegion(L);
1418 L = L->getParentLoop();
1422 L ? L->getSubLoops() : std::vector<Loop *>(
LI.begin(),
LI.end());
1424 for (
auto &SubLoop : SubLoops)
1425 if (R->contains(SubLoop)) {
1429 MaxLoopDepth = std::max(MaxLoopDepth, Stats.
MaxDepth);
1432 return {LoopNum, MaxLoopDepth};
1436 const DominatorTree &DT) {
1437 if (isa<UnreachableInst>(BB.getTerminator()))
1440 if (LI.isLoopHeader(&BB))
1445 if (!R.contains(&BB))
1450 bool DominatesAllPredecessors =
true;
1451 if (R.isTopLevelRegion()) {
1452 for (BasicBlock &I : *R.getEntry()->getParent()) {
1453 if (isa<ReturnInst>(I.getTerminator()) && !DT.dominates(&BB, &I)) {
1454 DominatesAllPredecessors =
false;
1459 for (
auto Pred : predecessors(R.getExit())) {
1460 if (R.contains(Pred) && !DT.dominates(&BB, Pred)) {
1461 DominatesAllPredecessors =
false;
1467 if (DominatesAllPredecessors)
1470 for (Instruction &Inst : BB)
1471 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1479 if (isa<MemSetInst>(CI) || isa<MemTransferInst>(CI))
1482 if (!CI->doesNotAccessMemory())
1484 if (CI->doesNotReturn())
1497 return It.first->getSecond();
1500 It.first->second = Result;
1506 std::unique_ptr<Region> LastValidRegion;
1507 auto ExpandedRegion = std::unique_ptr<Region>(R.getExpandedRegion());
1509 POLLY_DEBUG(dbgs() <<
"\tExpanding " << R.getNameStr() <<
"\n");
1511 while (ExpandedRegion) {
1514 Entry = std::make_unique<DetectionContext>(*ExpandedRegion,
AA,
1518 POLLY_DEBUG(dbgs() <<
"\t\tTrying " << ExpandedRegion->getNameStr()
1534 if (LastValidRegion) {
1538 LastValidRegion = std::move(ExpandedRegion);
1542 std::unique_ptr<Region>(LastValidRegion->getExpandedRegion());
1549 std::unique_ptr<Region>(ExpandedRegion->getExpandedRegion());
1554 if (LastValidRegion)
1555 dbgs() <<
"\tto " << LastValidRegion->getNameStr() <<
"\n";
1557 dbgs() <<
"\tExpanding " << R.getNameStr() <<
" failed\n";
1560 return LastValidRegion.release();
1564 for (
const BasicBlock *BB : R.blocks())
1565 if (R.contains(LI.getLoopFor(BB)))
1572 for (
auto &SubRegion : R) {
1585 std::unique_ptr<DetectionContext> &
Entry =
1587 Entry = std::make_unique<DetectionContext>(R,
AA,
false);
1590 bool DidBailout =
true;
1599 "With -polly-detect-keep-going, it is sufficient that if "
1600 "isValidRegion short-circuited, that SCoP is invalid");
1603 "isValidRegion must short-circuit iff the ScoP is invalid");
1613 for (
auto &SubRegion : R)
1622 std::vector<Region *> ToExpand;
1624 for (
auto &SubRegion : R)
1625 ToExpand.push_back(SubRegion.get());
1627 for (Region *CurrentRegion : ToExpand) {
1643 R.addSubRegion(ExpandedR,
true);
1653 for (
const BasicBlock *BB : CurRegion.blocks()) {
1654 Loop *L =
LI.getLoopFor(BB);
1655 if (L && L->getHeader() == BB) {
1656 if (CurRegion.contains(L)) {
1663 SmallVector<BasicBlock *, 1> Latches;
1664 L->getLoopLatches(Latches);
1665 for (BasicBlock *Latch : Latches)
1666 if (CurRegion.contains(Latch))
1673 for (BasicBlock *BB : CurRegion.blocks()) {
1685 for (BasicBlock::iterator I = BB->begin(), E = --BB->end(); I != E; ++I)
1700 int NumLoops)
const {
1706 for (
auto *BB : Context.
CurRegion.blocks())
1707 if (Context.
CurRegion.contains(
LI.getLoopFor(BB)))
1708 InstCount += BB->size();
1710 InstCount = InstCount / NumLoops;
1717 for (
auto *BB : Context.
CurRegion.blocks()) {
1718 auto *L =
LI.getLoopFor(BB);
1725 unsigned StmtsWithStoresInLoops = 0;
1726 for (
auto *LBB : L->blocks()) {
1727 bool MemStore =
false;
1728 for (
auto &I : *LBB)
1729 MemStore |= isa<StoreInst>(&I);
1730 StmtsWithStoresInLoops += MemStore;
1732 return (StmtsWithStoresInLoops > 1);
1750 int NumAffineLoops = NumLoops - Context.
BoxedLoopsSet.size();
1754 if (NumAffineLoops >= 2)
1776 POLLY_DEBUG(dbgs() <<
"Checking region: " << CurRegion.getNameStr()
1780 POLLY_DEBUG(dbgs() <<
"Top level region is invalid\n");
1786 if (CurRegion.getExit() &&
1787 isa<UnreachableInst>(CurRegion.getExit()->getTerminator())) {
1790 CurRegion.getExit(), DbgLoc);
1794 !CurRegion.getEntry()->getName().count(
OnlyRegion)) {
1796 dbgs() <<
"Region entry does not match -polly-only-region";
1803 for (BasicBlock *Pred : predecessors(CurRegion.getEntry())) {
1804 Instruction *PredTerm = Pred->getTerminator();
1805 if (isa<IndirectBrInst>(PredTerm) || isa<CallBrInst>(PredTerm))
1807 Context,
true, PredTerm, PredTerm->getDebugLoc());
1813 CurRegion.getEntry() ==
1814 &(CurRegion.getEntry()->getParent()->getEntryBlock()))
1827 &CurRegion, DbgLoc);
1842 for (
const Region *R : *
this) {
1843 unsigned LineEntry, LineExit;
1844 std::string FileName;
1847 DiagnosticScopFound Diagnostic(F, FileName, LineEntry, LineExit);
1848 F.getContext().diagnose(Diagnostic);
1866 enum Color { WHITE, GREY, BLACK };
1868 BasicBlock *REntry = R.getEntry();
1869 BasicBlock *RExit = R.getExit();
1871 DenseMap<const BasicBlock *, Color> BBColorMap;
1873 std::stack<std::pair<BasicBlock *, unsigned>> DFSStack;
1875 unsigned AdjacentBlockIndex = 0;
1876 BasicBlock *CurrBB, *SuccBB;
1880 for (
auto *BB : R.blocks())
1881 BBColorMap[BB] = WHITE;
1884 BBColorMap[CurrBB] = GREY;
1885 DFSStack.push(std::make_pair(CurrBB, 0));
1887 while (!DFSStack.empty()) {
1889 CurrBB = DFSStack.top().first;
1890 AdjacentBlockIndex = DFSStack.top().second;
1894 const Instruction *TInst = CurrBB->getTerminator();
1895 unsigned NSucc = TInst->getNumSuccessors();
1896 for (
unsigned I = AdjacentBlockIndex; I < NSucc;
1897 ++I, ++AdjacentBlockIndex) {
1898 SuccBB = TInst->getSuccessor(I);
1901 if (SuccBB == RExit || SuccBB == CurrBB)
1905 if (BBColorMap[SuccBB] == WHITE) {
1907 DFSStack.push(std::make_pair(CurrBB, I + 1));
1909 DFSStack.push(std::make_pair(SuccBB, 0));
1911 BBColorMap[SuccBB] = GREY;
1913 }
else if (BBColorMap[SuccBB] == GREY) {
1917 if (!
DT.dominates(SuccBB, CurrBB)) {
1919 DbgLoc = TInst->getDebugLoc();
1927 if (AdjacentBlockIndex == NSucc)
1928 BBColorMap[CurrBB] = BLACK;
1935 bool OnlyProfitable) {
1936 if (!OnlyProfitable) {
1939 std::max(MaxNumLoopsInScop.getValue(), (uint64_t)Stats.
NumLoops);
1941 NumScopsDepthZero++;
1947 NumScopsDepthThree++;
1949 NumScopsDepthFour++;
1951 NumScopsDepthFive++;
1953 NumScopsDepthLarger++;
1955 NumLoopsInProfScop += Stats.
NumLoops;
1956 MaxNumLoopsInProfScop =
1957 std::max(MaxNumLoopsInProfScop.getValue(), (uint64_t)Stats.
NumLoops);
1959 NumProfScopsDepthZero++;
1961 NumProfScopsDepthOne++;
1963 NumProfScopsDepthTwo++;
1965 NumProfScopsDepthThree++;
1967 NumProfScopsDepthFour++;
1969 NumProfScopsDepthFive++;
1971 NumProfScopsDepthLarger++;
1980 return DCMIt->second.get();
1985 return DC ? &DC->
Log :
nullptr;
2012 auto &LI = FAM.getResult<LoopAnalysis>(F);
2013 auto &RI = FAM.getResult<RegionInfoAnalysis>(F);
2014 auto &AA = FAM.getResult<AAManager>(F);
2015 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
2016 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2017 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
2025 FunctionAnalysisManager &FAM) {
2026 OS <<
"Detected Scops in Function " << F.getName() <<
"\n";
2028 for (
const Region *R : SD.ValidRegions)
2029 OS <<
"Valid Region for Scop: " << R->getNameStr() <<
'\n';
2032 return PreservedAnalyses::all();
static cl::opt< bool > Verify("polly-codegen-verify", cl::desc("Verify the function generated by Polly"), cl::Hidden, cl::cat(PollyCategory))
llvm::cl::OptionCategory PollyCategory
static const unsigned MIN_LOOP_TRIP_COUNT
The minimal trip count under which loops are considered unprofitable.
static cl::opt< bool, true > XPollyProcessUnprofitable("polly-process-unprofitable", cl::desc("Process scops that are unlikely to benefit from Polly optimizations."), cl::location(PollyProcessUnprofitable), cl::cat(PollyCategory))
static cl::opt< bool > AllowDifferentTypes("polly-allow-differing-element-types", cl::desc("Allow different element types for array accesses"), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static cl::opt< bool > AllowNonAffine("polly-allow-nonaffine", cl::desc("Allow non affine access functions in arrays"), cl::Hidden, cl::cat(PollyCategory))
STATISTIC(NumScopRegions, "Number of scops")
static cl::list< std::string > OnlyFunctions("polly-only-func", cl::desc("Only run on functions that match a regex. " "Multiple regexes can be comma separated. " "Scop detection will run on all functions that match " "ANY of the regexes provided."), cl::CommaSeparated, cl::cat(PollyCategory))
static cl::opt< bool > VerifyScops("polly-detect-verify", cl::desc("Verify the detected SCoPs after each transformation"), cl::Hidden, cl::cat(PollyCategory))
static bool hasExitingBlocks(Loop *L)
Check whether L has exiting blocks.
static cl::opt< std::string > OnlyRegion("polly-only-region", cl::desc("Only run on certain regions (The provided identifier must " "appear in the name of the region's entry block"), cl::value_desc("identifier"), cl::ValueRequired, cl::init(""), cl::cat(PollyCategory))
static bool regionWithoutLoops(Region &R, LoopInfo &LI)
static cl::opt< bool > KeepGoing("polly-detect-keep-going", cl::desc("Do not fail on the first error."), cl::Hidden, cl::cat(PollyCategory))
static cl::opt< int > ProfitabilityMinPerLoopInstructions("polly-detect-profitability-min-per-loop-insts", cl::desc("The minimal number of per-loop instructions before a single loop " "region is considered profitable"), cl::Hidden, cl::ValueRequired, cl::init(100000000), cl::cat(PollyCategory))
static cl::opt< bool, true > TrackFailures("polly-detect-track-failures", cl::desc("Track failure strings in detecting scop regions"), cl::location(PollyTrackFailures), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static bool doesStringMatchAnyRegex(StringRef Str, const cl::list< std::string > &RegexList)
Check if a string matches any regex in a list of regexes.
static cl::opt< bool > PollyAllowErrorBlocks("polly-allow-error-blocks", cl::desc("Allow to speculate on the execution of 'error blocks'."), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static cl::list< std::string > IgnoredFunctions("polly-ignore-func", cl::desc("Ignore functions that match a regex. " "Multiple regexes can be comma separated. " "Scop detection will ignore all functions that match " "ANY of the regexes provided."), cl::CommaSeparated, cl::cat(PollyCategory))
static cl::opt< bool > ReportLevel("polly-report", cl::desc("Print information about the activities of Polly"), cl::cat(PollyCategory))
static bool isErrorBlockImpl(BasicBlock &BB, const Region &R, LoopInfo &LI, const DominatorTree &DT)
static cl::opt< bool, true > PollyDelinearizeX("polly-delinearize", cl::desc("Delinearize array access functions"), cl::location(PollyDelinearize), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static cl::opt< bool, true > XPollyAllowUnsignedOperations("polly-allow-unsigned-operations", cl::desc("Allow unsigned operations such as comparisons or zero-extends."), cl::location(PollyAllowUnsignedOperations), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static void updateLoopCountStatistic(ScopDetection::LoopStats Stats, bool OnlyProfitable)
static cl::opt< bool > AllowNonAffineSubRegions("polly-allow-nonaffine-branches", cl::desc("Allow non affine conditions for branches"), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static cl::opt< bool, true > XAllowFullFunction("polly-detect-full-functions", cl::desc("Allow the detection of full functions"), cl::location(polly::PollyAllowFullFunction), cl::init(false), cl::cat(PollyCategory))
static cl::opt< bool, true > XPollyInvariantLoadHoisting("polly-invariant-load-hoisting", cl::desc("Hoist invariant loads."), cl::location(PollyInvariantLoadHoisting), cl::Hidden, cl::cat(PollyCategory))
static cl::opt< bool > AllowNonAffineSubLoops("polly-allow-nonaffine-loops", cl::desc("Allow non affine conditions for loops"), cl::Hidden, cl::cat(PollyCategory))
static cl::opt< bool, true > XPollyUseRuntimeAliasChecks("polly-use-runtime-alias-checks", cl::desc("Use runtime alias checks to resolve possible aliasing."), cl::location(PollyUseRuntimeAliasChecks), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static cl::opt< bool > IgnoreAliasing("polly-ignore-aliasing", cl::desc("Ignore possible aliasing of the array bases"), cl::Hidden, cl::cat(PollyCategory))
static cl::opt< bool > AllowModrefCall("polly-allow-modref-calls", cl::desc("Allow functions with known modref behavior"), cl::Hidden, cl::cat(PollyCategory))
Utility proxy to wrap the common members of LoadInst and StoreInst.
static MemAccInst dyn_cast(llvm::Value &V)
llvm::Value * getPointerOperand() const
Stores all errors that occurred during the detection.
void report(RejectReasonPtr Reject)
bool hasErrors() const
Returns true, if we store at least one error.
Base class of all reject reasons found during Scop detection.
virtual std::string getMessage() const =0
Generate a reasonable diagnostic message describing this error.
Pass to detect the maximal static control parts (Scops) of a function.
static void markFunctionAsInvalid(Function *F)
Mark the function as invalid so we will not extract any scop from the function.
bool addOverApproximatedRegion(Region *AR, DetectionContext &Context) const
Add the region AR as over approximated sub-region in Context.
bool isValidAccess(Instruction *Inst, const SCEV *AF, const SCEVUnknown *BP, DetectionContext &Context) const
Check if the memory access caused by Inst is valid.
bool onlyValidRequiredInvariantLoads(InvariantLoadsSetTy &RequiredILS, DetectionContext &Context) const
Check if the given loads could be invariant and can be hoisted.
bool isInvariant(Value &Val, const Region &Reg, DetectionContext &Ctx) const
Check if a value is invariant in the region Reg.
bool isReducibleRegion(Region &R, DebugLoc &DbgLoc) const
Check if a region is reducible or not.
bool computeAccessFunctions(DetectionContext &Context, const SCEVUnknown *BasePointer, std::shared_ptr< ArrayShape > Shape) const
Derive access functions for a given base pointer.
DetectionContext * getDetectionContext(const Region *R) const
Return the detection context for R, nullptr if R was invalid.
void removeCachedResultsRecursively(const Region &R)
Remove cached results for the children of R recursively.
bool hasSufficientCompute(DetectionContext &Context, int NumAffineLoops) const
Check if a region has sufficient compute instructions.
bool isProfitableRegion(DetectionContext &Context) const
Check if a region is profitable to optimize.
void emitMissedRemarks(const Function &F)
Emit rejection remarks for all rejected regions.
bool isValidLoop(Loop *L, DetectionContext &Context)
Is a loop valid with respect to a given region.
static ScopDetection::LoopStats countBeneficialLoops(Region *R, ScalarEvolution &SE, LoopInfo &LI, unsigned MinProfitableTrips)
Count the number of loops and the maximal loop depth in R.
const RejectLog * lookupRejectionLog(const Region *R) const
Return the set of rejection causes for R.
bool involvesMultiplePtrs(const SCEV *S0, const SCEV *S1, Loop *Scope) const
Check if S0 and S1 do contain multiple possibly aliasing pointers.
bool isValidSwitch(BasicBlock &BB, SwitchInst *SI, Value *Condition, bool IsLoopBranch, DetectionContext &Context) const
Check if the switch SI with condition Condition is valid.
bool isValidRegion(DetectionContext &Context)
Check if a region is a Scop.
Region * expandRegion(Region &R)
Try to expand the region R.
const DominatorTree & DT
Analyses used.
bool hasBaseAffineAccesses(DetectionContext &Context, const SCEVUnknown *BasePointer, Loop *Scope) const
Check if all accesses to a given BasePointer are affine.
OptimizationRemarkEmitter & ORE
OptimizationRemarkEmitter object used to emit diagnostic remarks.
bool hasAffineMemoryAccesses(DetectionContext &Context) const
Delinearize all non affine memory accesses and return false when there exists a non affine memory acc...
bool isValidMemoryAccess(MemAccInst Inst, DetectionContext &Context) const
Check if a memory access can be part of a Scop.
bool isValidCFG(BasicBlock &BB, bool IsLoopBranch, bool AllowUnreachable, DetectionContext &Context)
Check if the control flow in a basic block is valid.
void printLocations(Function &F)
Print the locations of all detected scops.
bool hasValidArraySizes(DetectionContext &Context, SmallVectorImpl< const SCEV * > &Sizes, const SCEVUnknown *BasePointer, Loop *Scope) const
Check if the dimension size of a delinearized array is valid.
DenseMap< std::tuple< const BasicBlock *, const Region * >, bool > ErrorBlockCache
Cache for the isErrorBlock function.
void removeCachedResults(const Region &R)
Remove cached results for R.
ScopDetection(const DominatorTree &DT, ScalarEvolution &SE, LoopInfo &LI, RegionInfo &RI, AAResults &AA, OptimizationRemarkEmitter &ORE)
bool hasPossiblyDistributableLoop(DetectionContext &Context) const
Check if the unique affine loop might be amendable to distribution.
bool isValidBranch(BasicBlock &BB, CondBrInst *BI, Value *Condition, bool IsLoopBranch, DetectionContext &Context)
Check if the branch BI with condition Condition is valid.
void verifyAnalysis()
Verify if all valid Regions in this Function are still valid after some transformations.
SmallVector< const SCEV *, 4 > getDelinearizationTerms(DetectionContext &Context, const SCEVUnknown *BasePointer) const
Find for a given base pointer terms that hint towards dimension sizes of a multi-dimensional array.
bool isValidInstruction(Instruction &Inst, DetectionContext &Context)
Check if an instruction can be part of a Scop.
bool isAffine(const SCEV *S, Loop *Scope, DetectionContext &Context) const
Check if the SCEV S is affine in the current Context.
DetectionContextMapTy DetectionContextMap
bool allBlocksValid(DetectionContext &Context)
Check if all basic block in the region are valid.
void findScops(Region &R)
Find the Scops in this region tree.
bool isValidIntrinsicInst(IntrinsicInst &II, DetectionContext &Context) const
Check if an intrinsic call can be part of a Scop.
std::string regionIsInvalidBecause(const Region *R) const
Get a message why a region is invalid.
bool isMaxRegionInScop(const Region &R, bool Verify=true)
Is the region is the maximum region of a Scop?
bool isValidCallInst(CallInst &CI, DetectionContext &Context) const
Check if a call instruction can be part of a Scop.
void verifyRegion(const Region &R)
Verify if R is still a valid part of Scop after some transformations.
static bool isValidFunction(Function &F)
Check if the function F is marked as invalid.
bool isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R)
Check if the block is a error block.
bool invalid(DetectionContext &Context, bool Assert, Args &&...Arguments) const
Track diagnostics for invalid scops.
bool canUseISLTripCount(Loop *L, DetectionContext &Context)
Can ISL compute the trip count of a loop.
bool isCompatibleType(Instruction *Inst, llvm::Type *Ty, DetectionContext &Context)
Filter out types that we do not support.
static ScopDetection::LoopStats countBeneficialSubLoops(Loop *L, ScalarEvolution &SE, unsigned MinProfitableTrips)
Count the number of loops and the maximal loop depth in L.
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.
std::shared_ptr< RejectReason > RejectReasonPtr
StringRef PollySkipFnAttr
A function attribute which will cause Polly to skip the function.
bool PollyAllowFullFunction
llvm::SetVector< llvm::AssertingVH< llvm::LoadInst > > InvariantLoadsSetTy
Type for a set of invariant loads.
bool isAffineExpr(const llvm::Region *R, llvm::Loop *Scope, const llvm::SCEV *Expression, llvm::ScalarEvolution &SE, InvariantLoadsSetTy *ILS=nullptr)
@ Value
MemoryKind::Value: Models an llvm::Value.
@ PHI
MemoryKind::PHI: Models PHI nodes within the SCoP.
void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, OptimizationRemarkEmitter &ORE)
Emit optimization remarks about the rejected regions to the user.
void getDebugLocation(const llvm::Region *R, unsigned &LineBegin, unsigned &LineEnd, std::string &FileName)
Get the location of a region from the debug info.
std::map< const Instruction *, MemAcc > MapInsnToMemAcc
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?
BBPair getBBPairForRegion(const Region *R)
Return the region delimiters (entry & exit block) of R.
bool PollyProcessUnprofitable
bool isHoistableLoad(llvm::LoadInst *LInst, llvm::Region &R, llvm::LoopInfo &LI, llvm::ScalarEvolution &SE, const llvm::DominatorTree &DT, const InvariantLoadsSetTy &KnownInvariantLoads)
Check if LInst can be hoisted in R.
bool PollyUseRuntimeAliasChecks
bool hasScalarDepsInsideRegion(const llvm::SCEV *Expr, const llvm::Region *R, llvm::Loop *Scope, bool AllowLoops, const InvariantLoadsSetTy &ILS)
Returns true when the SCEV contains references to instructions within the region.
bool PollyAllowUnsignedOperations
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.
std::pair< llvm::BasicBlock *, llvm::BasicBlock * > BBPair
Type to hold region delimiters (entry & exit block).
SmallVector< const SCEV *, 4 > DelinearizedSubscripts
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Result run(Function &F, FunctionAnalysisManager &FAM)
Context variables for SCoP detection.
BaseToAFs Accesses
Map a base pointer to all access functions accessing it.
InvariantLoadsSetTy RequiredILS
Loads that need to be invariant during execution.
bool hasLoads
The region has at least one load instruction.
bool IsInvalid
If this flag is set, the SCoP must eventually be rejected, even with KeepGoing.
bool HasUnknownAccess
Flag to indicate the region has at least one unknown access.
BoxedLoopsSetTy BoxedLoopsSet
The set of loops contained in non-affine regions.
MapInsnToMemAcc InsnToMemAcc
Map to memory access description for the corresponding LLVM instructions.
RejectLog Log
Container to remember rejection reasons for this region.
RegionSet NonAffineSubRegionSet
The set of non-affine subregions in the region we analyze.
llvm::SetVector< std::pair< const SCEVUnknown *, Loop * > > NonAffineAccesses
The set of base pointers with non-affine accesses.
bool hasStores
The region has at least one store instruction.
Helper data structure to collect statistics about loop counts.