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))
492 if (NonAffineRegion->contains(Load) &&
493 Load->getParent() != NonAffineRegion->getEntry())
505 SetVector<Value *> Values;
510 SmallPtrSet<Value *, 8> PtrVals;
511 for (
auto *V : Values) {
512 if (
auto *P2I = dyn_cast<PtrToIntInst>(V))
513 V = P2I->getOperand(0);
515 if (!V->getType()->isPointerTy())
518 const SCEV *PtrSCEV =
SE.getSCEVAtScope(V, Scope);
519 if (isa<SCEVConstant>(PtrSCEV))
522 auto *BasePtr = dyn_cast<SCEVUnknown>(
SE.getPointerBase(PtrSCEV));
526 Value *BasePtrVal = BasePtr->getValue();
527 if (PtrVals.insert(BasePtrVal).second) {
528 for (
auto *PtrVal : PtrVals)
529 if (PtrVal != BasePtrVal && !
AA.isNoAlias(PtrVal, BasePtrVal))
550 Value *Condition,
bool IsLoopBranch,
552 Loop *L =
LI.getLoopFor(&BB);
553 const SCEV *ConditionSCEV =
SE.getSCEVAtScope(Condition, L);
555 if (IsLoopBranch && L->isLoopLatch(&BB))
562 if (
isAffine(ConditionSCEV, L, Context))
570 ConditionSCEV, ConditionSCEV, SI);
574 Value *Condition,
bool IsLoopBranch,
577 if (isa<ConstantInt>(Condition))
580 if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
581 auto Opcode = BinOp->getOpcode();
582 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
583 Value *Op0 = BinOp->getOperand(0);
584 Value *Op1 = BinOp->getOperand(1);
590 if (
auto PHI = dyn_cast<PHINode>(Condition)) {
591 auto *Unique = dyn_cast_or_null<ConstantInt>(
593 if (Unique && (Unique->isZero() || Unique->isOne()))
597 if (
auto Load = dyn_cast<LoadInst>(Condition))
598 if (!IsLoopBranch && Context.
CurRegion.contains(Load)) {
604 if (!isa<ICmpInst>(Condition)) {
611 ICmpInst *ICmp = cast<ICmpInst>(Condition);
614 if (isa<UndefValue>(ICmp->getOperand(0)) ||
615 isa<UndefValue>(ICmp->getOperand(1)))
618 Loop *L =
LI.getLoopFor(&BB);
619 const SCEV *LHS =
SE.getSCEVAtScope(ICmp->getOperand(0), L);
620 const SCEV *RHS =
SE.getSCEVAtScope(ICmp->getOperand(1), L);
654 bool AllowUnreachable,
658 Instruction *TI = BB.getTerminator();
660 if (AllowUnreachable && isa<UnreachableInst>(TI))
664 if (isa<ReturnInst>(TI) && CurRegion.isTopLevelRegion())
667 if (isa<UncondBrInst>(TI))
670 if (
auto *BI = dyn_cast<CondBrInst>(TI)) {
671 Value *Condition = BI->getCondition();
672 if (isa<UndefValue>(Condition))
674 return isValidBranch(BB, BI, Condition, IsLoopBranch, Context);
677 if (
auto *SI = dyn_cast<SwitchInst>(TI)) {
678 Value *Condition = SI->getCondition();
679 if (isa<UndefValue>(Condition))
681 return isValidSwitch(BB, SI, Condition, IsLoopBranch, Context);
689 if (CI.doesNotReturn())
692 if (CI.doesNotAccessMemory())
695 if (
auto *II = dyn_cast<IntrinsicInst>(&CI))
699 Function *CalledFunction = CI.getCalledFunction();
702 if (CalledFunction ==
nullptr)
706 POLLY_DEBUG(dbgs() <<
"Allow call to debug function: "
707 << CalledFunction->getName() <<
'\n');
712 MemoryEffects ME =
AA.getMemoryEffects(CalledFunction);
713 if (ME.onlyAccessesArgPointees()) {
714 for (
const auto &Arg : CI.args()) {
715 if (!Arg->getType()->isPointerTy())
720 const SCEV *ArgSCEV =
721 SE.getSCEVAtScope(Arg,
LI.getLoopFor(CI.getParent()));
722 if (ArgSCEV->isZero())
725 auto *BP = dyn_cast<SCEVUnknown>(
SE.getPointerBase(ArgSCEV));
736 Context.
AST.addUnknown(&CI);
740 if (ME.onlyReadsMemory()) {
746 Context.
AST.addUnknown(&CI);
761 Loop *L =
LI.getLoopFor(II.getParent());
765 const SCEVUnknown *BP;
767 switch (II.getIntrinsicID()) {
769 case Intrinsic::memmove:
770 case Intrinsic::memcpy:
771 AF =
SE.getSCEVAtScope(cast<MemTransferInst>(II).getSource(), L);
773 BP = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AF));
779 case Intrinsic::memset:
780 AF =
SE.getSCEVAtScope(cast<MemIntrinsic>(II).getDest(), L);
782 BP = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AF));
789 if (!
isAffine(
SE.getSCEVAtScope(cast<MemIntrinsic>(II).getLength(), L), L,
804 if (isa<Argument>(Val) || isa<Constant>(Val))
807 Instruction *I = dyn_cast<Instruction>(&Val);
811 if (!Reg.contains(I))
817 if (
auto LI = dyn_cast<LoadInst>(I)) {
818 Ctx.RequiredILS.insert(
LI);
839class SCEVRemoveMax final :
public SCEVRewriteVisitor<SCEVRemoveMax> {
841 SCEVRemoveMax(ScalarEvolution &SE, std::vector<const SCEV *> *Terms)
842 : SCEVRewriteVisitor(SE), Terms(Terms) {}
844 static const SCEV *rewrite(
const SCEV *Scev, ScalarEvolution &SE,
845 std::vector<const SCEV *> *Terms =
nullptr) {
846 SCEVRemoveMax Rewriter(SE, Terms);
847 return Rewriter.visit(Scev);
850 const SCEV *visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
851 if ((Expr->getNumOperands() == 2) && Expr->getOperand(0)->isZero()) {
852 auto Res = visit(Expr->getOperand(1));
854 (*Terms).push_back(
Res);
862 std::vector<const SCEV *> *Terms;
866SmallVector<const SCEV *, 4>
868 const SCEVUnknown *BasePointer)
const {
869 SmallVector<const SCEV *, 4> Terms;
870 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
871 std::vector<const SCEV *> MaxTerms;
872 SCEVRemoveMax::rewrite(
Pair.second,
SE, &MaxTerms);
873 if (!MaxTerms.empty()) {
874 for (
const SCEV *Max : MaxTerms)
876 SE.getTruncateOrSignExtend(Max,
Pair.second->getType()));
887 if (
auto *AF = dyn_cast<SCEVAddExpr>(
Pair.second)) {
888 for (
auto Op : AF->operands()) {
889 if (
auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
890 collectParametricTerms(
SE, AF2, Terms);
891 if (
auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
892 SmallVector<SCEVUse, 0> Operands;
894 for (
const SCEV *MulOp : AF2->operands()) {
895 if (
auto *Const = dyn_cast<SCEVConstant>(MulOp))
896 Operands.push_back(Const);
897 if (
auto *Unknown = dyn_cast<SCEVUnknown>(MulOp)) {
898 if (
auto *Inst = dyn_cast<Instruction>(Unknown->getValue())) {
900 Operands.push_back(MulOp);
903 Operands.push_back(MulOp);
908 Terms.push_back(
SE.getMulExpr(Operands));
913 collectParametricTerms(
SE,
Pair.second, Terms);
919 SmallVectorImpl<const SCEV *> &Sizes,
920 const SCEVUnknown *BasePointer,
928 if (Sizes.size() == 0)
931 Value *BaseValue = BasePointer->getValue();
933 for (
const SCEV *DelinearizedSize : Sizes) {
936 if (!
isAffine(DelinearizedSize,
nullptr, Context)) {
940 if (
auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
941 auto *V = dyn_cast<Value>(Unknown->getValue());
942 if (
auto *Load = dyn_cast<LoadInst>(V)) {
952 Context,
true, DelinearizedSize,
953 Context.
Accesses[BasePointer].front().first, BaseValue);
961 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
962 const Instruction *Insn =
Pair.first;
963 const SCEV *AF =
Pair.second;
965 if (!
isAffine(AF, Scope, Context)) {
985 std::shared_ptr<ArrayShape> Shape)
const {
986 Value *BaseValue = BasePointer->getValue();
987 bool BasePtrHasNonAffine =
false;
989 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
990 const Instruction *Insn =
Pair.first;
991 auto *AF =
Pair.second;
992 AF = SCEVRemoveMax::rewrite(AF,
SE);
993 bool IsNonAffine =
false;
994 TempMemoryAccesses.insert(std::make_pair(Insn,
MemAcc(Insn, Shape)));
995 MemAcc *Acc = &TempMemoryAccesses.find(Insn)->second;
996 auto *Scope =
LI.getLoopFor(Insn->getParent());
1004 if (Shape->DelinearizedSizes.size() == 0) {
1008 Shape->DelinearizedSizes);
1019 BasePtrHasNonAffine =
true;
1029 if (!BasePtrHasNonAffine)
1030 Context.
InsnToMemAcc.insert(TempMemoryAccesses.begin(),
1031 TempMemoryAccesses.end());
1037 const SCEVUnknown *BasePointer,
1038 Loop *Scope)
const {
1039 auto Shape = std::shared_ptr<ArrayShape>(
new ArrayShape(BasePointer));
1043 findArrayDimensions(
SE, Terms, Shape->DelinearizedSizes,
1060 auto *BasePointer =
Pair.first;
1061 auto *Scope =
Pair.second;
1072 const SCEVUnknown *BP,
1078 auto *BV = BP->getValue();
1079 if (isa<UndefValue>(BV))
1083 if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BV))
1091 AF =
SE.getMinusSCEV(AF, BP);
1094 if (!isa<MemIntrinsic>(Inst)) {
1095 Size =
SE.getElementSize(Inst);
1098 SE.getEffectiveSCEVType(PointerType::getUnqual(
SE.getContext()));
1099 Size =
SE.getConstant(SizeTy, 8);
1112 bool IsVariantInNonAffineLoop =
false;
1113 SetVector<const Loop *> Loops;
1115 for (
const Loop *L : Loops)
1117 IsVariantInNonAffineLoop =
true;
1119 auto *Scope =
LI.getLoopFor(Inst->getParent());
1120 bool IsAffine = !IsVariantInNonAffineLoop &&
isAffine(AF, Scope, Context);
1122 if (isa<MemIntrinsic>(Inst) && !IsAffine) {
1126 Context.
Accesses[BP].push_back({Inst, AF});
1130 std::make_pair(BP,
LI.getLoopFor(Inst->getParent())));
1141 AAMDNodes AATags = Inst->getAAMetadata();
1142 AliasSet &AS = Context.
AST.getAliasSetFor(
1143 MemoryLocation::getBeforeOrAfter(BP->getValue(), AATags));
1145 if (!AS.isMustAlias()) {
1147 bool CanBuildRunTimeCheck =
true;
1154 auto ASPointers = AS.getPointers();
1162 const unsigned int VariantSize = VariantLS.size(),
1163 InvariantSize = InvariantLS.size();
1165 for (
const Value *Ptr : ASPointers) {
1166 Instruction *Inst = dyn_cast<Instruction>(
const_cast<Value *
>(Ptr));
1167 if (Inst && Context.
CurRegion.contains(Inst)) {
1168 auto *Load = dyn_cast<LoadInst>(Inst);
1169 if (Load && InvariantLS.count(Load))
1173 if (VariantLS.count(Load))
1174 VariantLS.remove(Load);
1176 InvariantLS.insert(Load);
1178 CanBuildRunTimeCheck =
false;
1179 VariantLS.insert(Load);
1184 if (InvariantSize == InvariantLS.size() &&
1185 VariantSize == VariantLS.size())
1189 if (CanBuildRunTimeCheck)
1201 Loop *L =
LI.getLoopFor(Inst->getParent());
1202 const SCEV *AccessFunction =
SE.getSCEVAtScope(Ptr, L);
1203 const SCEVUnknown *BasePointer;
1205 BasePointer = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1207 return isValidAccess(Inst, AccessFunction, BasePointer, Context);
1215 if (isa<ScalableVectorType>(Ty))
1223 for (
auto &Op : Inst.operands()) {
1224 auto *OpInst = dyn_cast<Instruction>(&Op);
1233 auto *
PHI = dyn_cast<PHINode>(OpInst);
1235 for (User *U :
PHI->users()) {
1236 auto *UI = dyn_cast<Instruction>(U);
1237 if (!UI || !UI->isTerminator())
1246 if (isa<LandingPadInst>(&Inst) || isa<ResumeInst>(&Inst))
1253 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1260 if (!Inst.mayReadOrWriteMemory()) {
1261 if (!isa<AllocaInst>(Inst))
1269 Context.
hasStores |= isa<StoreInst>(MemInst);
1270 Context.
hasLoads |= isa<LoadInst>(MemInst);
1271 if (!MemInst.isSimple())
1288 SmallVector<BasicBlock *, 4> ExitingBlocks;
1289 L->getExitingBlocks(ExitingBlocks);
1290 return !ExitingBlocks.empty();
1305 SmallVector<BasicBlock *, 4> LoopControlBlocks;
1306 L->getExitingBlocks(LoopControlBlocks);
1307 L->getLoopLatches(LoopControlBlocks);
1308 for (BasicBlock *ControlBB : LoopControlBlocks) {
1309 if (!
isValidCFG(*ControlBB,
true,
false, Context)) {
1357 SmallVector<BasicBlock *, 4> ExitBlocks;
1358 L->getExitBlocks(ExitBlocks);
1359 BasicBlock *TheExitBlock = ExitBlocks[0];
1360 for (BasicBlock *ExitBB : ExitBlocks) {
1361 if (TheExitBlock != ExitBB)
1369 Region *R =
RI.getRegionFor(L->getHeader());
1370 while (R != &Context.
CurRegion && !R->contains(L))
1377 const SCEV *LoopCount =
SE.getBackedgeTakenCount(L);
1385 unsigned MinProfitableTrips) {
1386 const SCEV *TripCount =
SE.getBackedgeTakenCount(L);
1389 int MaxLoopDepth = 1;
1390 if (MinProfitableTrips > 0)
1391 if (
auto *TripCountC = dyn_cast<SCEVConstant>(TripCount))
1392 if (TripCountC->getType()->getScalarSizeInBits() <= 64)
1393 if (TripCountC->getValue()->getZExtValue() <= MinProfitableTrips)
1396 for (
auto &SubLoop : *L) {
1399 MaxLoopDepth = std::max(MaxLoopDepth, Stats.
MaxDepth + 1);
1402 return {NumLoops, MaxLoopDepth};
1407 LoopInfo &
LI,
unsigned MinProfitableTrips) {
1409 int MaxLoopDepth = 0;
1411 auto L =
LI.getLoopFor(R->getEntry());
1415 if (L && R->contains(L)) {
1416 L = R->outermostLoopInRegion(L);
1417 L = L->getParentLoop();
1421 L ? L->getSubLoops() : std::vector<Loop *>(
LI.begin(),
LI.end());
1423 for (
auto &SubLoop : SubLoops)
1424 if (R->contains(SubLoop)) {
1428 MaxLoopDepth = std::max(MaxLoopDepth, Stats.
MaxDepth);
1431 return {LoopNum, MaxLoopDepth};
1435 const DominatorTree &DT) {
1436 if (isa<UnreachableInst>(BB.getTerminator()))
1439 if (LI.isLoopHeader(&BB))
1444 if (!R.contains(&BB))
1449 bool DominatesAllPredecessors =
true;
1450 if (R.isTopLevelRegion()) {
1451 for (BasicBlock &I : *R.getEntry()->getParent()) {
1452 if (isa<ReturnInst>(I.getTerminator()) && !DT.dominates(&BB, &I)) {
1453 DominatesAllPredecessors =
false;
1458 for (
auto Pred : predecessors(R.getExit())) {
1459 if (R.contains(Pred) && !DT.dominates(&BB, Pred)) {
1460 DominatesAllPredecessors =
false;
1466 if (DominatesAllPredecessors)
1469 for (Instruction &Inst : BB)
1470 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1478 if (isa<MemSetInst>(CI) || isa<MemTransferInst>(CI))
1481 if (!CI->doesNotAccessMemory())
1483 if (CI->doesNotReturn())
1496 return It.first->getSecond();
1499 It.first->second = Result;
1505 std::unique_ptr<Region> LastValidRegion;
1506 auto ExpandedRegion = std::unique_ptr<Region>(R.getExpandedRegion());
1508 POLLY_DEBUG(dbgs() <<
"\tExpanding " << R.getNameStr() <<
"\n");
1510 while (ExpandedRegion) {
1513 Entry = std::make_unique<DetectionContext>(*ExpandedRegion,
AA,
1517 POLLY_DEBUG(dbgs() <<
"\t\tTrying " << ExpandedRegion->getNameStr()
1533 if (LastValidRegion) {
1537 LastValidRegion = std::move(ExpandedRegion);
1541 std::unique_ptr<Region>(LastValidRegion->getExpandedRegion());
1548 std::unique_ptr<Region>(ExpandedRegion->getExpandedRegion());
1553 if (LastValidRegion)
1554 dbgs() <<
"\tto " << LastValidRegion->getNameStr() <<
"\n";
1556 dbgs() <<
"\tExpanding " << R.getNameStr() <<
" failed\n";
1559 return LastValidRegion.release();
1563 for (
const BasicBlock *BB : R.blocks())
1564 if (R.contains(LI.getLoopFor(BB)))
1571 for (
auto &SubRegion : R) {
1584 std::unique_ptr<DetectionContext> &
Entry =
1586 Entry = std::make_unique<DetectionContext>(R,
AA,
false);
1589 bool DidBailout =
true;
1598 "With -polly-detect-keep-going, it is sufficient that if "
1599 "isValidRegion short-circuited, that SCoP is invalid");
1602 "isValidRegion must short-circuit iff the ScoP is invalid");
1612 for (
auto &SubRegion : R)
1621 std::vector<Region *> ToExpand;
1623 for (
auto &SubRegion : R)
1624 ToExpand.push_back(SubRegion.get());
1626 for (Region *CurrentRegion : ToExpand) {
1642 R.addSubRegion(ExpandedR,
true);
1652 for (
const BasicBlock *BB : CurRegion.blocks()) {
1653 Loop *L =
LI.getLoopFor(BB);
1654 if (L && L->getHeader() == BB) {
1655 if (CurRegion.contains(L)) {
1662 SmallVector<BasicBlock *, 1> Latches;
1663 L->getLoopLatches(Latches);
1664 for (BasicBlock *Latch : Latches)
1665 if (CurRegion.contains(Latch))
1672 for (BasicBlock *BB : CurRegion.blocks()) {
1684 for (BasicBlock::iterator I = BB->begin(), E = --BB->end(); I != E; ++I)
1699 int NumLoops)
const {
1705 for (
auto *BB : Context.
CurRegion.blocks())
1706 if (Context.
CurRegion.contains(
LI.getLoopFor(BB)))
1707 InstCount += BB->size();
1709 InstCount = InstCount / NumLoops;
1716 for (
auto *BB : Context.
CurRegion.blocks()) {
1717 auto *L =
LI.getLoopFor(BB);
1724 unsigned StmtsWithStoresInLoops = 0;
1725 for (
auto *LBB : L->blocks()) {
1726 bool MemStore =
false;
1727 for (
auto &I : *LBB)
1728 MemStore |= isa<StoreInst>(&I);
1729 StmtsWithStoresInLoops += MemStore;
1731 return (StmtsWithStoresInLoops > 1);
1749 int NumAffineLoops = NumLoops - Context.
BoxedLoopsSet.size();
1753 if (NumAffineLoops >= 2)
1775 POLLY_DEBUG(dbgs() <<
"Checking region: " << CurRegion.getNameStr()
1779 POLLY_DEBUG(dbgs() <<
"Top level region is invalid\n");
1785 if (CurRegion.getExit() &&
1786 isa<UnreachableInst>(CurRegion.getExit()->getTerminator())) {
1789 CurRegion.getExit(), DbgLoc);
1793 !CurRegion.getEntry()->getName().count(
OnlyRegion)) {
1795 dbgs() <<
"Region entry does not match -polly-only-region";
1802 for (BasicBlock *Pred : predecessors(CurRegion.getEntry())) {
1803 Instruction *PredTerm = Pred->getTerminator();
1804 if (isa<IndirectBrInst>(PredTerm) || isa<CallBrInst>(PredTerm))
1806 Context,
true, PredTerm, PredTerm->getDebugLoc());
1812 CurRegion.getEntry() ==
1813 &(CurRegion.getEntry()->getParent()->getEntryBlock()))
1826 &CurRegion, DbgLoc);
1841 for (
const Region *R : *
this) {
1842 unsigned LineEntry, LineExit;
1843 std::string FileName;
1846 DiagnosticScopFound Diagnostic(F, FileName, LineEntry, LineExit);
1847 F.getContext().diagnose(Diagnostic);
1865 enum Color { WHITE, GREY, BLACK };
1867 BasicBlock *REntry = R.getEntry();
1868 BasicBlock *RExit = R.getExit();
1870 DenseMap<const BasicBlock *, Color> BBColorMap;
1872 std::stack<std::pair<BasicBlock *, unsigned>> DFSStack;
1874 unsigned AdjacentBlockIndex = 0;
1875 BasicBlock *CurrBB, *SuccBB;
1879 for (
auto *BB : R.blocks())
1880 BBColorMap[BB] = WHITE;
1883 BBColorMap[CurrBB] = GREY;
1884 DFSStack.push(std::make_pair(CurrBB, 0));
1886 while (!DFSStack.empty()) {
1888 CurrBB = DFSStack.top().first;
1889 AdjacentBlockIndex = DFSStack.top().second;
1893 const Instruction *TInst = CurrBB->getTerminator();
1894 unsigned NSucc = TInst->getNumSuccessors();
1895 for (
unsigned I = AdjacentBlockIndex; I < NSucc;
1896 ++I, ++AdjacentBlockIndex) {
1897 SuccBB = TInst->getSuccessor(I);
1900 if (SuccBB == RExit || SuccBB == CurrBB)
1904 if (BBColorMap[SuccBB] == WHITE) {
1906 DFSStack.push(std::make_pair(CurrBB, I + 1));
1908 DFSStack.push(std::make_pair(SuccBB, 0));
1910 BBColorMap[SuccBB] = GREY;
1912 }
else if (BBColorMap[SuccBB] == GREY) {
1916 if (!
DT.dominates(SuccBB, CurrBB)) {
1918 DbgLoc = TInst->getDebugLoc();
1926 if (AdjacentBlockIndex == NSucc)
1927 BBColorMap[CurrBB] = BLACK;
1934 bool OnlyProfitable) {
1935 if (!OnlyProfitable) {
1938 std::max(MaxNumLoopsInScop.getValue(), (uint64_t)Stats.
NumLoops);
1940 NumScopsDepthZero++;
1946 NumScopsDepthThree++;
1948 NumScopsDepthFour++;
1950 NumScopsDepthFive++;
1952 NumScopsDepthLarger++;
1954 NumLoopsInProfScop += Stats.
NumLoops;
1955 MaxNumLoopsInProfScop =
1956 std::max(MaxNumLoopsInProfScop.getValue(), (uint64_t)Stats.
NumLoops);
1958 NumProfScopsDepthZero++;
1960 NumProfScopsDepthOne++;
1962 NumProfScopsDepthTwo++;
1964 NumProfScopsDepthThree++;
1966 NumProfScopsDepthFour++;
1968 NumProfScopsDepthFive++;
1970 NumProfScopsDepthLarger++;
1979 return DCMIt->second.get();
1984 return DC ? &DC->
Log :
nullptr;
2011 auto &LI = FAM.getResult<LoopAnalysis>(F);
2012 auto &RI = FAM.getResult<RegionInfoAnalysis>(F);
2013 auto &AA = FAM.getResult<AAManager>(F);
2014 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
2015 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2016 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
2024 FunctionAnalysisManager &FAM) {
2025 OS <<
"Detected Scops in Function " << F.getName() <<
"\n";
2027 for (
const Region *R : SD.ValidRegions)
2028 OS <<
"Valid Region for Scop: " << R->getNameStr() <<
'\n';
2031 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.