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 Terms.insert(Terms.begin(), MaxTerms.begin(), MaxTerms.end());
886 if (
auto *AF = dyn_cast<SCEVAddExpr>(
Pair.second)) {
887 for (
auto Op : AF->operands()) {
888 if (
auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
889 collectParametricTerms(
SE, AF2, Terms);
890 if (
auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
891 SmallVector<SCEVUse, 0> Operands;
893 for (
const SCEV *MulOp : AF2->operands()) {
894 if (
auto *Const = dyn_cast<SCEVConstant>(MulOp))
895 Operands.push_back(Const);
896 if (
auto *Unknown = dyn_cast<SCEVUnknown>(MulOp)) {
897 if (
auto *Inst = dyn_cast<Instruction>(Unknown->getValue())) {
899 Operands.push_back(MulOp);
902 Operands.push_back(MulOp);
907 Terms.push_back(
SE.getMulExpr(Operands));
912 collectParametricTerms(
SE,
Pair.second, Terms);
918 SmallVectorImpl<const SCEV *> &Sizes,
919 const SCEVUnknown *BasePointer,
927 if (Sizes.size() == 0)
930 Value *BaseValue = BasePointer->getValue();
932 for (
const SCEV *DelinearizedSize : Sizes) {
935 if (!
isAffine(DelinearizedSize,
nullptr, Context)) {
939 if (
auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
940 auto *V = dyn_cast<Value>(Unknown->getValue());
941 if (
auto *Load = dyn_cast<LoadInst>(V)) {
951 Context,
true, DelinearizedSize,
952 Context.
Accesses[BasePointer].front().first, BaseValue);
960 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
961 const Instruction *Insn =
Pair.first;
962 const SCEV *AF =
Pair.second;
964 if (!
isAffine(AF, Scope, Context)) {
984 std::shared_ptr<ArrayShape> Shape)
const {
985 Value *BaseValue = BasePointer->getValue();
986 bool BasePtrHasNonAffine =
false;
988 for (
const auto &
Pair : Context.
Accesses[BasePointer]) {
989 const Instruction *Insn =
Pair.first;
990 auto *AF =
Pair.second;
991 AF = SCEVRemoveMax::rewrite(AF,
SE);
992 bool IsNonAffine =
false;
993 TempMemoryAccesses.insert(std::make_pair(Insn,
MemAcc(Insn, Shape)));
994 MemAcc *Acc = &TempMemoryAccesses.find(Insn)->second;
995 auto *Scope =
LI.getLoopFor(Insn->getParent());
1003 if (Shape->DelinearizedSizes.size() == 0) {
1007 Shape->DelinearizedSizes);
1018 BasePtrHasNonAffine =
true;
1028 if (!BasePtrHasNonAffine)
1029 Context.
InsnToMemAcc.insert(TempMemoryAccesses.begin(),
1030 TempMemoryAccesses.end());
1036 const SCEVUnknown *BasePointer,
1037 Loop *Scope)
const {
1038 auto Shape = std::shared_ptr<ArrayShape>(
new ArrayShape(BasePointer));
1042 findArrayDimensions(
SE, Terms, Shape->DelinearizedSizes,
1059 auto *BasePointer =
Pair.first;
1060 auto *Scope =
Pair.second;
1071 const SCEVUnknown *BP,
1077 auto *BV = BP->getValue();
1078 if (isa<UndefValue>(BV))
1082 if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BV))
1090 AF =
SE.getMinusSCEV(AF, BP);
1093 if (!isa<MemIntrinsic>(Inst)) {
1094 Size =
SE.getElementSize(Inst);
1097 SE.getEffectiveSCEVType(PointerType::getUnqual(
SE.getContext()));
1098 Size =
SE.getConstant(SizeTy, 8);
1111 bool IsVariantInNonAffineLoop =
false;
1112 SetVector<const Loop *> Loops;
1114 for (
const Loop *L : Loops)
1116 IsVariantInNonAffineLoop =
true;
1118 auto *Scope =
LI.getLoopFor(Inst->getParent());
1119 bool IsAffine = !IsVariantInNonAffineLoop &&
isAffine(AF, Scope, Context);
1121 if (isa<MemIntrinsic>(Inst) && !IsAffine) {
1125 Context.
Accesses[BP].push_back({Inst, AF});
1129 std::make_pair(BP,
LI.getLoopFor(Inst->getParent())));
1140 AAMDNodes AATags = Inst->getAAMetadata();
1141 AliasSet &AS = Context.
AST.getAliasSetFor(
1142 MemoryLocation::getBeforeOrAfter(BP->getValue(), AATags));
1144 if (!AS.isMustAlias()) {
1146 bool CanBuildRunTimeCheck =
true;
1153 auto ASPointers = AS.getPointers();
1161 const unsigned int VariantSize = VariantLS.size(),
1162 InvariantSize = InvariantLS.size();
1164 for (
const Value *Ptr : ASPointers) {
1165 Instruction *Inst = dyn_cast<Instruction>(
const_cast<Value *
>(Ptr));
1166 if (Inst && Context.
CurRegion.contains(Inst)) {
1167 auto *Load = dyn_cast<LoadInst>(Inst);
1168 if (Load && InvariantLS.count(Load))
1172 if (VariantLS.count(Load))
1173 VariantLS.remove(Load);
1175 InvariantLS.insert(Load);
1177 CanBuildRunTimeCheck =
false;
1178 VariantLS.insert(Load);
1183 if (InvariantSize == InvariantLS.size() &&
1184 VariantSize == VariantLS.size())
1188 if (CanBuildRunTimeCheck)
1200 Loop *L =
LI.getLoopFor(Inst->getParent());
1201 const SCEV *AccessFunction =
SE.getSCEVAtScope(Ptr, L);
1202 const SCEVUnknown *BasePointer;
1204 BasePointer = dyn_cast<SCEVUnknown>(
SE.getPointerBase(AccessFunction));
1206 return isValidAccess(Inst, AccessFunction, BasePointer, Context);
1214 if (isa<ScalableVectorType>(Ty))
1222 for (
auto &Op : Inst.operands()) {
1223 auto *OpInst = dyn_cast<Instruction>(&Op);
1232 auto *
PHI = dyn_cast<PHINode>(OpInst);
1234 for (User *U :
PHI->users()) {
1235 auto *UI = dyn_cast<Instruction>(U);
1236 if (!UI || !UI->isTerminator())
1245 if (isa<LandingPadInst>(&Inst) || isa<ResumeInst>(&Inst))
1252 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1259 if (!Inst.mayReadOrWriteMemory()) {
1260 if (!isa<AllocaInst>(Inst))
1268 Context.
hasStores |= isa<StoreInst>(MemInst);
1269 Context.
hasLoads |= isa<LoadInst>(MemInst);
1270 if (!MemInst.isSimple())
1287 SmallVector<BasicBlock *, 4> ExitingBlocks;
1288 L->getExitingBlocks(ExitingBlocks);
1289 return !ExitingBlocks.empty();
1304 SmallVector<BasicBlock *, 4> LoopControlBlocks;
1305 L->getExitingBlocks(LoopControlBlocks);
1306 L->getLoopLatches(LoopControlBlocks);
1307 for (BasicBlock *ControlBB : LoopControlBlocks) {
1308 if (!
isValidCFG(*ControlBB,
true,
false, Context)) {
1356 SmallVector<BasicBlock *, 4> ExitBlocks;
1357 L->getExitBlocks(ExitBlocks);
1358 BasicBlock *TheExitBlock = ExitBlocks[0];
1359 for (BasicBlock *ExitBB : ExitBlocks) {
1360 if (TheExitBlock != ExitBB)
1368 Region *R =
RI.getRegionFor(L->getHeader());
1369 while (R != &Context.
CurRegion && !R->contains(L))
1376 const SCEV *LoopCount =
SE.getBackedgeTakenCount(L);
1384 unsigned MinProfitableTrips) {
1385 const SCEV *TripCount =
SE.getBackedgeTakenCount(L);
1388 int MaxLoopDepth = 1;
1389 if (MinProfitableTrips > 0)
1390 if (
auto *TripCountC = dyn_cast<SCEVConstant>(TripCount))
1391 if (TripCountC->getType()->getScalarSizeInBits() <= 64)
1392 if (TripCountC->getValue()->getZExtValue() <= MinProfitableTrips)
1395 for (
auto &SubLoop : *L) {
1398 MaxLoopDepth = std::max(MaxLoopDepth, Stats.
MaxDepth + 1);
1401 return {NumLoops, MaxLoopDepth};
1406 LoopInfo &
LI,
unsigned MinProfitableTrips) {
1408 int MaxLoopDepth = 0;
1410 auto L =
LI.getLoopFor(R->getEntry());
1414 if (L && R->contains(L)) {
1415 L = R->outermostLoopInRegion(L);
1416 L = L->getParentLoop();
1420 L ? L->getSubLoopsVector() : std::vector<Loop *>(
LI.begin(),
LI.end());
1422 for (
auto &SubLoop : SubLoops)
1423 if (R->contains(SubLoop)) {
1427 MaxLoopDepth = std::max(MaxLoopDepth, Stats.
MaxDepth);
1430 return {LoopNum, MaxLoopDepth};
1434 const DominatorTree &DT) {
1435 if (isa<UnreachableInst>(BB.getTerminator()))
1438 if (LI.isLoopHeader(&BB))
1443 if (!R.contains(&BB))
1448 bool DominatesAllPredecessors =
true;
1449 if (R.isTopLevelRegion()) {
1450 for (BasicBlock &I : *R.getEntry()->getParent()) {
1451 if (isa<ReturnInst>(I.getTerminator()) && !DT.dominates(&BB, &I)) {
1452 DominatesAllPredecessors =
false;
1457 for (
auto Pred : predecessors(R.getExit())) {
1458 if (R.contains(Pred) && !DT.dominates(&BB, Pred)) {
1459 DominatesAllPredecessors =
false;
1465 if (DominatesAllPredecessors)
1468 for (Instruction &Inst : BB)
1469 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1477 if (isa<MemSetInst>(CI) || isa<MemTransferInst>(CI))
1480 if (!CI->doesNotAccessMemory())
1482 if (CI->doesNotReturn())
1495 return It.first->getSecond();
1498 It.first->second = Result;
1504 std::unique_ptr<Region> LastValidRegion;
1505 auto ExpandedRegion = std::unique_ptr<Region>(R.getExpandedRegion());
1507 POLLY_DEBUG(dbgs() <<
"\tExpanding " << R.getNameStr() <<
"\n");
1509 while (ExpandedRegion) {
1512 Entry = std::make_unique<DetectionContext>(*ExpandedRegion,
AA,
1516 POLLY_DEBUG(dbgs() <<
"\t\tTrying " << ExpandedRegion->getNameStr()
1532 if (LastValidRegion) {
1536 LastValidRegion = std::move(ExpandedRegion);
1540 std::unique_ptr<Region>(LastValidRegion->getExpandedRegion());
1547 std::unique_ptr<Region>(ExpandedRegion->getExpandedRegion());
1552 if (LastValidRegion)
1553 dbgs() <<
"\tto " << LastValidRegion->getNameStr() <<
"\n";
1555 dbgs() <<
"\tExpanding " << R.getNameStr() <<
" failed\n";
1558 return LastValidRegion.release();
1562 for (
const BasicBlock *BB : R.blocks())
1563 if (R.contains(LI.getLoopFor(BB)))
1570 for (
auto &SubRegion : R) {
1583 std::unique_ptr<DetectionContext> &
Entry =
1585 Entry = std::make_unique<DetectionContext>(R,
AA,
false);
1588 bool DidBailout =
true;
1597 "With -polly-detect-keep-going, it is sufficient that if "
1598 "isValidRegion short-circuited, that SCoP is invalid");
1601 "isValidRegion must short-circuit iff the ScoP is invalid");
1611 for (
auto &SubRegion : R)
1620 std::vector<Region *> ToExpand;
1622 for (
auto &SubRegion : R)
1623 ToExpand.push_back(SubRegion.get());
1625 for (Region *CurrentRegion : ToExpand) {
1641 R.addSubRegion(ExpandedR,
true);
1651 for (
const BasicBlock *BB : CurRegion.blocks()) {
1652 Loop *L =
LI.getLoopFor(BB);
1653 if (L && L->getHeader() == BB) {
1654 if (CurRegion.contains(L)) {
1661 SmallVector<BasicBlock *, 1> Latches;
1662 L->getLoopLatches(Latches);
1663 for (BasicBlock *Latch : Latches)
1664 if (CurRegion.contains(Latch))
1671 for (BasicBlock *BB : CurRegion.blocks()) {
1683 for (BasicBlock::iterator I = BB->begin(), E = --BB->end(); I != E; ++I)
1698 int NumLoops)
const {
1704 for (
auto *BB : Context.
CurRegion.blocks())
1705 if (Context.
CurRegion.contains(
LI.getLoopFor(BB)))
1706 InstCount += BB->size();
1708 InstCount = InstCount / NumLoops;
1715 for (
auto *BB : Context.
CurRegion.blocks()) {
1716 auto *L =
LI.getLoopFor(BB);
1723 unsigned StmtsWithStoresInLoops = 0;
1724 for (
auto *LBB : L->blocks()) {
1725 bool MemStore =
false;
1726 for (
auto &I : *LBB)
1727 MemStore |= isa<StoreInst>(&I);
1728 StmtsWithStoresInLoops += MemStore;
1730 return (StmtsWithStoresInLoops > 1);
1748 int NumAffineLoops = NumLoops - Context.
BoxedLoopsSet.size();
1752 if (NumAffineLoops >= 2)
1774 POLLY_DEBUG(dbgs() <<
"Checking region: " << CurRegion.getNameStr()
1778 POLLY_DEBUG(dbgs() <<
"Top level region is invalid\n");
1784 if (CurRegion.getExit() &&
1785 isa<UnreachableInst>(CurRegion.getExit()->getTerminator())) {
1788 CurRegion.getExit(), DbgLoc);
1792 !CurRegion.getEntry()->getName().count(
OnlyRegion)) {
1794 dbgs() <<
"Region entry does not match -polly-only-region";
1801 for (BasicBlock *Pred : predecessors(CurRegion.getEntry())) {
1802 Instruction *PredTerm = Pred->getTerminator();
1803 if (isa<IndirectBrInst>(PredTerm) || isa<CallBrInst>(PredTerm))
1805 Context,
true, PredTerm, PredTerm->getDebugLoc());
1811 CurRegion.getEntry() ==
1812 &(CurRegion.getEntry()->getParent()->getEntryBlock()))
1825 &CurRegion, DbgLoc);
1840 for (
const Region *R : *
this) {
1841 unsigned LineEntry, LineExit;
1842 std::string FileName;
1845 DiagnosticScopFound Diagnostic(F, FileName, LineEntry, LineExit);
1846 F.getContext().diagnose(Diagnostic);
1864 enum Color { WHITE, GREY, BLACK };
1866 BasicBlock *REntry = R.getEntry();
1867 BasicBlock *RExit = R.getExit();
1869 DenseMap<const BasicBlock *, Color> BBColorMap;
1871 std::stack<std::pair<BasicBlock *, unsigned>> DFSStack;
1873 unsigned AdjacentBlockIndex = 0;
1874 BasicBlock *CurrBB, *SuccBB;
1878 for (
auto *BB : R.blocks())
1879 BBColorMap[BB] = WHITE;
1882 BBColorMap[CurrBB] = GREY;
1883 DFSStack.push(std::make_pair(CurrBB, 0));
1885 while (!DFSStack.empty()) {
1887 CurrBB = DFSStack.top().first;
1888 AdjacentBlockIndex = DFSStack.top().second;
1892 const Instruction *TInst = CurrBB->getTerminator();
1893 unsigned NSucc = TInst->getNumSuccessors();
1894 for (
unsigned I = AdjacentBlockIndex; I < NSucc;
1895 ++I, ++AdjacentBlockIndex) {
1896 SuccBB = TInst->getSuccessor(I);
1899 if (SuccBB == RExit || SuccBB == CurrBB)
1903 if (BBColorMap[SuccBB] == WHITE) {
1905 DFSStack.push(std::make_pair(CurrBB, I + 1));
1907 DFSStack.push(std::make_pair(SuccBB, 0));
1909 BBColorMap[SuccBB] = GREY;
1911 }
else if (BBColorMap[SuccBB] == GREY) {
1915 if (!
DT.dominates(SuccBB, CurrBB)) {
1917 DbgLoc = TInst->getDebugLoc();
1925 if (AdjacentBlockIndex == NSucc)
1926 BBColorMap[CurrBB] = BLACK;
1933 bool OnlyProfitable) {
1934 if (!OnlyProfitable) {
1937 std::max(MaxNumLoopsInScop.getValue(), (uint64_t)Stats.
NumLoops);
1939 NumScopsDepthZero++;
1945 NumScopsDepthThree++;
1947 NumScopsDepthFour++;
1949 NumScopsDepthFive++;
1951 NumScopsDepthLarger++;
1953 NumLoopsInProfScop += Stats.
NumLoops;
1954 MaxNumLoopsInProfScop =
1955 std::max(MaxNumLoopsInProfScop.getValue(), (uint64_t)Stats.
NumLoops);
1957 NumProfScopsDepthZero++;
1959 NumProfScopsDepthOne++;
1961 NumProfScopsDepthTwo++;
1963 NumProfScopsDepthThree++;
1965 NumProfScopsDepthFour++;
1967 NumProfScopsDepthFive++;
1969 NumProfScopsDepthLarger++;
1978 return DCMIt->second.get();
1983 return DC ? &DC->
Log :
nullptr;
2010 auto &LI = FAM.getResult<LoopAnalysis>(F);
2011 auto &RI = FAM.getResult<RegionInfoAnalysis>(F);
2012 auto &AA = FAM.getResult<AAManager>(F);
2013 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
2014 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2015 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
2023 FunctionAnalysisManager &FAM) {
2024 OS <<
"Detected Scops in Function " << F.getName() <<
"\n";
2026 for (
const Region *R : SD.ValidRegions)
2027 OS <<
"Valid Region for Scop: " << R->getNameStr() <<
'\n';
2030 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.