29#include "llvm/ADT/APInt.h"
30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/PostOrderIterator.h"
32#include "llvm/ADT/Sequence.h"
33#include "llvm/ADT/SmallPtrSet.h"
34#include "llvm/ADT/SmallSet.h"
35#include "llvm/ADT/Statistic.h"
36#include "llvm/ADT/StringExtras.h"
37#include "llvm/Analysis/AliasAnalysis.h"
38#include "llvm/Analysis/AssumptionCache.h"
39#include "llvm/Analysis/Loads.h"
40#include "llvm/Analysis/LoopInfo.h"
41#include "llvm/Analysis/OptimizationRemarkEmitter.h"
42#include "llvm/Analysis/RegionInfo.h"
43#include "llvm/Analysis/RegionIterator.h"
44#include "llvm/Analysis/ScalarEvolution.h"
45#include "llvm/Analysis/ScalarEvolutionExpressions.h"
46#include "llvm/IR/BasicBlock.h"
47#include "llvm/IR/ConstantRange.h"
48#include "llvm/IR/DataLayout.h"
49#include "llvm/IR/DebugLoc.h"
50#include "llvm/IR/Dominators.h"
51#include "llvm/IR/Function.h"
52#include "llvm/IR/InstrTypes.h"
53#include "llvm/IR/Instruction.h"
54#include "llvm/IR/Instructions.h"
55#include "llvm/IR/Module.h"
56#include "llvm/IR/Type.h"
57#include "llvm/IR/Value.h"
58#include "llvm/Support/Compiler.h"
59#include "llvm/Support/Debug.h"
60#include "llvm/Support/ErrorHandling.h"
61#include "llvm/Support/raw_ostream.h"
74#define DEBUG_TYPE "polly-scops"
76STATISTIC(AssumptionsAliasing,
"Number of aliasing assumptions taken.");
77STATISTIC(AssumptionsInbounds,
"Number of inbounds assumptions taken.");
78STATISTIC(AssumptionsWrapping,
"Number of wrapping assumptions taken.");
79STATISTIC(AssumptionsUnsigned,
"Number of unsigned assumptions taken.");
80STATISTIC(AssumptionsComplexity,
"Number of too complex SCoPs.");
81STATISTIC(AssumptionsUnprofitable,
"Number of unprofitable SCoPs.");
82STATISTIC(AssumptionsErrorBlock,
"Number of error block assumptions taken.");
83STATISTIC(AssumptionsInfiniteLoop,
"Number of bounded loop assumptions taken.");
85 "Number of invariant loads assumptions taken.");
87 "Number of delinearization assumptions taken.");
89STATISTIC(NumScops,
"Number of feasible SCoPs after ScopInfo");
90STATISTIC(NumLoopsInScop,
"Number of loops in scops");
91STATISTIC(NumBoxedLoops,
"Number of boxed loops in SCoPs after ScopInfo");
92STATISTIC(NumAffineLoops,
"Number of affine loops in SCoPs after ScopInfo");
94STATISTIC(NumScopsDepthZero,
"Number of scops with maximal loop depth 0");
95STATISTIC(NumScopsDepthOne,
"Number of scops with maximal loop depth 1");
96STATISTIC(NumScopsDepthTwo,
"Number of scops with maximal loop depth 2");
97STATISTIC(NumScopsDepthThree,
"Number of scops with maximal loop depth 3");
98STATISTIC(NumScopsDepthFour,
"Number of scops with maximal loop depth 4");
99STATISTIC(NumScopsDepthFive,
"Number of scops with maximal loop depth 5");
101 "Number of scops with maximal loop depth 6 and larger");
102STATISTIC(MaxNumLoopsInScop,
"Maximal number of loops in scops");
104STATISTIC(NumValueWrites,
"Number of scalar value writes after ScopInfo");
106 NumValueWritesInLoops,
107 "Number of scalar value writes nested in affine loops after ScopInfo");
108STATISTIC(NumPHIWrites,
"Number of scalar phi writes after ScopInfo");
110 "Number of scalar phi writes nested in affine loops after ScopInfo");
111STATISTIC(NumSingletonWrites,
"Number of singleton writes after ScopInfo");
113 "Number of singleton writes nested in affine loops after ScopInfo");
127 "polly-remarks-minimal",
128 cl::desc(
"Do not emit remarks about assumptions that are known"),
133 cl::desc(
"Abort if an isl error is encountered"),
137 "polly-precise-inbounds",
138 cl::desc(
"Take more precise inbounds assumptions (do not scale well)"),
142 "polly-ignore-parameter-bounds",
144 "Do not add parameter bounds and do no gist simplify sets accordingly"),
148 "polly-precise-fold-accesses",
149 cl::desc(
"Fold memory accesses to model more possible delinearizations "
150 "(does not scale well)"),
156 "polly-use-llvm-names",
157 cl::desc(
"Use LLVM-IR names when deriving statement names"),
162 cl::desc(
"Output instructions per ScopStmt"),
165static cl::list<std::string>
IslArgs(
"polly-isl-arg",
166 cl::value_desc(
"argument"),
167 cl::desc(
"Option passed to ISL"),
181 S =
S.lower_bound_val(
type, dim, V);
183 S =
S.upper_bound_val(
type, dim, V);
185 if (
Range.isFullSet())
193 if (
Range.isSignWrappedSet()) {
207 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr);
211 if (!
S->contains(BasePtrLI))
214 ScalarEvolution &SE = *
S->getSE();
216 const SCEV *OriginBaseSCEV =
217 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand()));
221 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV);
222 if (!OriginBaseSCEVUnknown)
225 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(),
232 const char *BaseName)
234 std::string BasePtrName =
290 uint64_t Factor, ScalarEvolution &SE) {
291 if (Factor == 1 || Sizes.empty() || !Sizes.back())
294 const SCEV *Innermost = Sizes.back();
296 SE.getMulExpr(Innermost, SE.getConstant(Innermost->getType(), Factor));
303 auto OldElementSize =
DL.getTypeAllocSizeInBits(
ElementType);
304 auto NewElementSize =
DL.getTypeAllocSizeInBits(NewElementType);
306 if (NewElementSize == OldElementSize || NewElementSize == 0)
310 if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) {
311 CanonicalType = NewElementType;
313 auto GCD = std::gcd((uint64_t)NewElementSize, (uint64_t)OldElementSize);
314 CanonicalType = IntegerType::get(
ElementType->getContext(), GCD);
328 uint64_t CanonicalSize =
DL.getTypeAllocSizeInBits(CanonicalType);
329 if (CanonicalSize == 0 || (uint64_t)OldElementSize % CanonicalSize != 0)
334 uint64_t Factor = (uint64_t)OldElementSize / CanonicalSize;
344 bool CheckConsistency) {
345 int SharedDims = std::min(NewSizes.size(),
DimensionSizes.size());
346 int ExtraDimsNew = NewSizes.size() - SharedDims;
349 if (CheckConsistency) {
350 for (
int i = 0; i < SharedDims; i++) {
351 auto *NewSize = NewSizes[i + ExtraDimsNew];
353 if (NewSize && KnownSize && NewSize != KnownSize)
384#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
401 OS <<
" " << Size <<
" ";
420 assert(!
Id.is_null() &&
"Output dimension didn't have an ID");
425 void *User =
Id.get_user();
434 unsigned DimsArray = SAI->getNumberOfDimensions();
437 ArraySpace.map_from_domain_and_range(ArraySpace));
441 for (
int i = DimsArray - 1; i > 0; i--) {
442 auto *DimSize = SAI->getDimensionSize(i);
443 auto *DimSizeCst = dyn_cast<SCEVConstant>(DimSize);
450 if (DimSize->isZero())
462 Modulo = Modulo.
pullback(DivModAff);
466 Divide = Divide.
floor();
467 Divide = Divide.
add(PrevVar);
468 Divide = Divide.
pullback(DivModAff);
471 DivModAff = DivModAff.set_aff(i, Modulo);
472 DivModAff = DivModAff.set_aff(i - 1, Divide);
490 assert(DimsArray >= DimsAccess);
491 unsigned DimsMissing = DimsArray - DimsAccess;
494 auto &DL = BB->getModule()->getDataLayout();
495 unsigned ArrayElemSize = SAI->getElemSizeInBytes();
501 for (
auto i : seq<unsigned>(0, DimsMissing))
504 for (
auto i : seq<unsigned>(DimsMissing, DimsArray))
519 if (DimsAccess == 1) {
547 if (ElemBytes > ArrayElemSize) {
548 assert(ElemBytes % ArrayElemSize == 0 &&
549 "Loaded element size should be multiple of canonical element size");
553 for (
auto i : seq<unsigned>(0, DimsArray - 1))
561 int Scale = DimsAccess == 1 ? 1 : Num;
568 Map = Map.add_constraint(
C);
575 Map = Map.add_constraint(
C);
584 llvm_unreachable(
"Requested a reduction operator string for a memory "
585 "access which isn't a reduction");
587 llvm_unreachable(
"Requested a reduction operator string for a internal "
600 llvm_unreachable(
"Unknown reduction type");
605 void *User = ArrayId.get_user();
612 void *User = ArrayId.get_user();
669 Space = Space.align_params(
Statement->getDomainSpace());
712 Outside = Outside.
unite(DimOutside);
717 Outside = Outside.
params();
723 Outside = Outside.remove_divs();
748 LengthMap = LengthMap.align_params(SubscriptMap.
get_space());
749 SubscriptMap = SubscriptMap.align_params(LengthMap.
get_space());
750 LengthMap = LengthMap.sum(SubscriptMap);
756 ScalarEvolution *SE =
Statement->getParent()->getSE();
759 if (isa<MemIntrinsic>(MAI))
762 Value *Ptr = MAI.getPointerOperand();
763 if (!Ptr || !SE->isSCEVable(Ptr->getType()))
766 const SCEV *PtrSCEV = SE->getSCEV(Ptr);
767 if (isa<SCEVCouldNotCompute>(PtrSCEV))
770 const SCEV *BasePtrSCEV = SE->getPointerBase(PtrSCEV);
771 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV))
772 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV);
774 const ConstantRange &
Range = SE->getSignedRange(PtrSCEV);
775 if (
Range.isFullSet())
778 if (
Range.isUpperWrapped() ||
Range.isSignWrappedSet())
781 bool isWrapping =
Range.isSignWrappedSet();
783 unsigned BW =
Range.getBitWidth();
784 const auto One = APInt(BW, 1);
785 const auto LB = isWrapping ?
Range.getLower() :
Range.getSignedMin();
786 const auto UB = isWrapping ? (
Range.getUpper() - One) :
Range.getSignedMax();
788 auto Min = LB.sdiv(APInt(BW, ElementSize));
789 auto Max = UB.sdiv(APInt(BW, ElementSize)) + One;
791 assert(Min.sle(Max) &&
"Minimum expected to be less or equal than max");
801 if (
Sizes.size() < 2 || isa<SCEVConstant>(
Sizes[1]))
808 for (
int i = Size - 2; i >= 0; --i) {
818 Space = Space.align_params(SpaceSize);
823 for (
int j = 0; j < Size; ++j)
828 for (
int j = 0; j < Size; ++j)
829 if (j < i || j > i + 1)
835 C =
C.set_constant_si(-1);
838 MapTwo = MapTwo.add_constraint(
C);
843 MapTwo = MapTwo.add_constraint(
C);
844 MapTwo = MapTwo.upper_bound_si(
isl::dim::in, i + 1, -1);
846 MapOne = MapOne.
unite(MapTwo);
899 for (
int i = 0, Size =
Subscripts.size(); i < Size; ++i) {
925 static const std::string TypeStrings[] = {
"",
"_Read",
"_Write",
"_MayWrite"};
926 const std::string Access = TypeStrings[
AccType] + utostr(Stmt->
size());
937 Sizes.push_back(
nullptr);
938 for (
unsigned i = 1; i < SAI->getNumberOfDimensions(); i++)
939 Sizes.push_back(SAI->getDimensionSize(i));
942 static const std::string TypeStrings[] = {
"",
"_Read",
"_Write",
"_MayWrite"};
943 const std::string Access = TypeStrings[
AccType] + utostr(Stmt->
size());
986 OS.indent(12) <<
"ReadAccess :=\t";
989 OS.indent(12) <<
"MustWriteAccess :=\t";
992 OS.indent(12) <<
"MayWriteAccess :=\t";
1004#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1010 PWACtx PWAC = Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock());
1012 StmtDom = StmtDom.reset_tuple_id();
1039 for (
unsigned i = 0; i < lastDimension; ++i)
1055 Schedule = Schedule.
reverse();
1056 NextScatt = NextScatt.
lexmin();
1074 for (
auto i : seq<int>(0, Size - 1))
1076 StrideX = StrideX.fix_si(
isl::dim::set, Size - 1, StrideWidth);
1102 assert(OriginalDomainSpace.has_equal_tuples(NewDomainSpace));
1114 "Partial READ accesses not supported");
1119 "Must specify the array that is accessed");
1121 auto *SAI =
static_cast<ScopArrayInfo *
>(NewArrayId.get_user());
1122 assert(SAI &&
"Must set a ScopArrayInfo");
1124 if (SAI->isArrayKind() && SAI->getBasePtrOriginSAI()) {
1129 "Access functions to indirect arrays must have an invariant and "
1130 "hoisted base pointer");
1135 unsigned Dims = SAI->getNumberOfDimensions();
1137 assert(SpaceSize == Dims &&
"Access dims must match array dims");
1159 if (Schedule.is_null())
1162 if (Schedule.is_empty())
1164 isl::map M = M.from_union_map(Schedule);
1173 "New domain is not a subset of old domain!");
1182 MAL.emplace_front(Access);
1184 Instruction *AccessVal = cast<Instruction>(Access->
getAccessValue());
1232 std::vector<Instruction *> EntryBlockInstructions)
1294 OS <<
"Instructions {\n";
1297 OS.indent(16) << *Inst <<
"\n";
1299 OS.indent(12) <<
"}\n";
1304 OS.indent(12) <<
"Domain :=\n";
1309 OS.indent(16) <<
"n/a\n";
1311 OS.indent(12) <<
"Schedule :=\n";
1316 OS.indent(16) <<
"n/a\n";
1321 if (PrintInstructions)
1325#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1333 assert(Found &&
"Expected access data not found");
1338 assert(Found &&
"Expected access data not found");
1343 assert(Found &&
"Expected access data not found");
1348 assert(Found &&
"Expected access data not found");
1363 if (Predicate(MA)) {
1365 Parent.removeAccessData(MA);
1368 llvm::erase_if(
MemAccs, Predicate);
1373 if (AfterHoisting) {
1379 Parent.removeAccessData(MA);
1384 It->second.remove(MA);
1385 if (It->second.empty())
1399 Parent.addAccessFunction(Access);
1402 Parent.addAccessData(Access);
1421class SCEVSensitiveParameterRewriter final
1422 :
public SCEVRewriteVisitor<SCEVSensitiveParameterRewriter> {
1423 const ValueToValueMap &VMap;
1426 SCEVSensitiveParameterRewriter(
const ValueToValueMap &VMap,
1427 ScalarEvolution &SE)
1428 : SCEVRewriteVisitor(SE), VMap(VMap) {}
1430 static const SCEV *rewrite(
const SCEV *E, ScalarEvolution &SE,
1431 const ValueToValueMap &VMap) {
1432 SCEVSensitiveParameterRewriter SSPR(VMap, SE);
1433 return SSPR.visit(E);
1436 const SCEV *visitAddRecExpr(
const SCEVAddRecExpr *E) {
1437 const SCEV *Start = visit(E->getStart());
1438 const SCEV *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0),
1439 visit(E->getStepRecurrence(SE)),
1440 E->getLoop(), SCEV::FlagNone);
1441 return SE.getAddExpr(Start, AddRec);
1444 const SCEV *visitUnknown(
const SCEVUnknown *E) {
1445 if (
auto *NewValue = VMap.lookup(E->getValue()))
1446 return SE.getUnknown(NewValue);
1452class SCEVFindInsideScop :
public SCEVTraversal<SCEVFindInsideScop> {
1453 const ValueToValueMap &VMap;
1454 bool FoundInside =
false;
1458 SCEVFindInsideScop(
const ValueToValueMap &VMap, ScalarEvolution &SE,
1460 : SCEVTraversal(*this), VMap(VMap),
S(
S) {}
1462 static bool hasVariant(
const SCEV *E, ScalarEvolution &SE,
1463 const ValueToValueMap &VMap,
const Scop *
S) {
1464 SCEVFindInsideScop SFIS(VMap, SE,
S);
1466 return SFIS.FoundInside;
1469 bool follow(
const SCEV *E) {
1470 if (
auto *AddRec = dyn_cast<SCEVAddRecExpr>(E)) {
1471 FoundInside |=
S->getRegion().contains(AddRec->getLoop());
1472 }
else if (
auto *Unknown = dyn_cast<SCEVUnknown>(E)) {
1473 if (Instruction *I = dyn_cast<Instruction>(Unknown->getValue()))
1474 FoundInside |=
S->getRegion().contains(I) && !VMap.count(I);
1476 return !FoundInside;
1479 bool isDone() {
return FoundInside; }
1498 std::string ParameterName =
"p_" + std::to_string(
getNumParams() - 1);
1500 if (
const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
1501 Value *Val = ValueParameter->getValue();
1508 ParameterName = Val->getName().str();
1509 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) {
1510 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets();
1511 if (LoadOrigin->hasName()) {
1512 ParameterName +=
"_loaded_from_";
1514 LI->getPointerOperand()->stripInBoundsOffsets()->getName();
1523 const_cast<void *
>((
const void *)Parameter));
1528 for (
const SCEV *Parameter : NewParameters) {
1551 ConstantRange SRange =
SE->getSignedRange(Parameter);
1590 if (!
S.hasErrorBlock()) {
1591 auto DomainParameters =
S.getDomains().params();
1592 AssumptionContext = AssumptionContext.
gist_params(DomainParameters);
1595 AssumptionContext = AssumptionContext.
gist_params(
S.getContext());
1596 return AssumptionContext;
1641 return DIt->getSecond();
1643 auto &RI = *
R.getRegionInfo();
1644 auto *BBR = RI.getRegionFor(BB);
1645 while (BBR->getEntry() == BB)
1646 BBR = BBR->getParent();
1652 OptimizationRemarkEmitter &
ORE,
int ID)
1660 SmallVector<char *, 8> IslArgv;
1661 IslArgv.reserve(1 +
IslArgs.size());
1664 IslArgv.push_back(
const_cast<char *
>(
"-polly-isl-arg"));
1666 for (std::string &Arg :
IslArgs)
1667 IslArgv.push_back(
const_cast<char *
>(Arg.c_str()));
1688 LoopInfo &LI, DominatorTree &
DT,
1690 OptimizationRemarkEmitter &
ORE,
int ID) {
1701 for (BasicBlock *BB : Stmt.
getRegion()->blocks()) {
1707 for (Instruction &Inst : *BB)
1712 if (StmtMapIt !=
StmtMap.end())
1713 llvm::erase(StmtMapIt->second, &Stmt);
1720 bool AfterHoisting) {
1721 for (
auto StmtIt =
Stmts.begin(), StmtEnd =
Stmts.end(); StmtIt != StmtEnd;) {
1722 if (!ShouldDelete(*StmtIt)) {
1730 SmallVector<MemoryAccess *, 16> MAList(StmtIt->begin(), StmtIt->end());
1732 StmtIt->removeSingleMemoryAccess(MA, AfterHoisting);
1735 StmtIt =
Stmts.erase(StmtIt);
1760 if (!MA->isMustWrite() || !MA->isOriginalValueKind())
1762 auto *Inst = dyn_cast_or_null<Instruction>(MA->getAccessValue());
1774 [AfterHoisting](
ScopStmt &Stmt) ->
bool {
1779 bool RemoveStmt = Stmt.
isEmpty();
1782 if (!RemoveStmt && AfterHoisting) {
1783 bool OnlyRead =
true;
1792 RemoveStmt = OnlyRead;
1800 LoadInst *LInst = dyn_cast<LoadInst>(Val);
1805 LInst = cast<LoadInst>(Rep);
1807 Type *Ty = LInst->getType();
1808 const SCEV *PointerSCEV =
SE->getSCEV(LInst->getPointerOperand());
1810 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
1813 auto &MAs = IAClass.InvariantAccesses;
1814 for (
auto *MA : MAs)
1815 if (MA->getAccessInstruction() == Val)
1823 ArrayRef<const SCEV *> Sizes,
1825 const char *BaseName) {
1826 assert((BasePtr || BaseName) &&
1827 "BasePtr and BaseName can not be nullptr at the same time.");
1828 assert(!(BasePtr && BaseName) &&
"BaseName is redundant.");
1832 auto &DL =
getFunction().getParent()->getDataLayout();
1834 DL,
this, BaseName));
1837 SAI->updateElementType(ElementType);
1843 auto &DL =
getFunction().getParent()->getDataLayout();
1844 uint64_t AccessElemSize = DL.getTypeAllocSize(ElementType);
1845 uint64_t CanonicalElemSize = SAI->getElemSizeInBytes();
1847 SmallVector<const SCEV *, 4> CanonicalSizes(Sizes);
1848 if (CanonicalElemSize != 0 && AccessElemSize % CanonicalElemSize == 0)
1854 if (!SAI->updateSizes(CanonicalSizes))
1861 const std::string &BaseName,
1862 const std::vector<unsigned> &Sizes) {
1864 std::vector<const SCEV *> SCEVSizes;
1866 for (
auto size : Sizes)
1870 SCEVSizes.push_back(
nullptr);
1884 assert(SAI &&
"No ScopArrayInfo available for this base pointer");
1902 std::string ExitName, EntryName;
1904 return EntryName +
"---" + ExitName;
1908 std::string ExitName, EntryName;
1909 raw_string_ostream ExitStr(ExitName);
1910 raw_string_ostream EntryStr(EntryName);
1912 R.getEntry()->printAsOperand(EntryStr,
false);
1915 R.getExit()->printAsOperand(ExitStr,
false);
1917 ExitName =
"FunctionExit";
1919 return std::make_pair(EntryName, ExitName);
1951 unsigned OptimizableStmtsOrLoops = 0;
1952 for (
auto &Stmt : *
this) {
1953 if (Stmt.getNumIterators() == 0)
1956 bool ContainsArrayAccs =
false;
1957 bool ContainsScalarAccs =
false;
1958 for (
auto *MA : Stmt) {
1961 ContainsArrayAccs |= MA->isLatestArrayKind();
1962 ContainsScalarAccs |= MA->isLatestScalarKind();
1965 if (!ScalarsAreUnprofitable || (ContainsArrayAccs && !ContainsScalarAccs))
1966 OptimizableStmtsOrLoops += Stmt.getNumIterators();
1969 return OptimizableStmtsOrLoops > 1;
1987 auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase);
1988 if (!PointerBaseInst)
1991 auto *BasePtrStmt =
getStmtFor(PointerBaseInst);
1995 return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst);
2001 return "No-aliasing";
2005 return "No-overflows";
2007 return "Signed-unsigned";
2009 return "Low complexity";
2011 return "Profitable";
2015 return "Finite loop";
2017 return "Invariant load";
2019 return "Delinearization";
2021 llvm_unreachable(
"Unknown AssumptionKind!");
2061 AssumptionsAliasing++;
2064 AssumptionsInbounds++;
2067 AssumptionsWrapping++;
2070 AssumptionsUnsigned++;
2073 AssumptionsComplexity++;
2076 AssumptionsUnprofitable++;
2079 AssumptionsErrorBlock++;
2082 AssumptionsInfiniteLoop++;
2085 AssumptionsInvariantLoad++;
2088 AssumptionsDelinearization++;
2092 auto Suffix = Sign ==
AS_ASSUMPTION ?
" assumption:\t" :
" restriction:\t";
2093 std::string Msg =
toString(
Kind) + Suffix + stringFromIslObj(Set);
2095 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"AssumpRestrict", Loc, BB)
2098 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"AssumpRestrict", Loc,
2144 POLLY_DEBUG(dbgs() <<
"Invalidate SCoP because of reason " <<
Kind <<
"\n");
2152 OS.indent(4) <<
Context <<
"\n";
2154 OS.indent(4) <<
"Assumed Context:\n";
2157 OS.indent(4) <<
"Invalid Context:\n";
2160 OS.indent(4) <<
"Defined Behavior Context:\n";
2164 OS.indent(4) <<
"<unavailable>\n";
2168 OS.indent(4) <<
"p" << Dim++ <<
": " << *Parameter <<
"\n";
2174 if (
Pair.second.size() == 0)
2177 noOfGroups +=
Pair.second.size();
2180 OS.indent(4) <<
"Alias Groups (" << noOfGroups <<
"):\n";
2182 OS.indent(8) <<
"n/a\n";
2189 if (
Pair.second.empty()) {
2190 OS.indent(8) <<
"[[";
2192 OS <<
" <" << MMANonReadOnly.first <<
", " << MMANonReadOnly.second
2199 OS.indent(8) <<
"[[";
2200 OS <<
" <" << MMAReadOnly.first <<
", " << MMAReadOnly.second <<
">";
2202 OS <<
" <" << MMANonReadOnly.first <<
", " << MMANonReadOnly.second
2211 OS <<
"Statements {\n";
2213 for (
const ScopStmt &Stmt : *
this) {
2215 Stmt.
print(OS, PrintInstructions);
2218 OS.indent(4) <<
"}\n";
2227 OS.indent(4) <<
"}\n";
2229 OS.indent(4) <<
"Arrays (Bounds as pw_affs) {\n";
2232 Array->print(OS,
true);
2234 OS.indent(4) <<
"}\n";
2238 OS.indent(4) <<
"Function: " <<
getFunction().getName() <<
"\n";
2239 OS.indent(4) <<
"Region: " <<
getNameStr() <<
"\n";
2241 OS.indent(4) <<
"Invariant Accesses: {\n";
2243 const auto &MAs = IAClass.InvariantAccesses;
2245 OS.indent(12) <<
"Class Pointer: " << *IAClass.IdentifyingPointer <<
"\n";
2247 MAs.front()->print(OS);
2248 OS.indent(12) <<
"Execution Context: " << IAClass.ExecutionContext
2252 OS.indent(4) <<
"}\n";
2259#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2268 bool IsInsideDomain) {
2274 PWACtx PWAC =
Affinator.getPwAff(E, BB, RecordedAssumptions, IsInsideDomain);
2275 if (!PWAC.first.is_null()) {
2282 Affinator.takeNonNegativeAssumption(PWAC, RecordedAssumptions);
2286 auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
2288 return Affinator.getPwAff(
SE->getZero(E->getType()), BB, RecordedAssumptions);
2313 if (!Predicate(*MA))
2317 isl::map AccessDomain = MA->getAccessRelation();
2319 Accesses = Accesses.
unite(AccessDomain);
2353 return Tree.get_map();
2373 bool Changed =
false;
2378 if (StmtDomain.
is_subset(NewStmtDomain))
2383 NewStmtDomain = NewStmtDomain.
coalesce();
2396 std::vector<Instruction *> Instructions) {
2397 assert(BB &&
"Unexpected nullptr!");
2398 Stmts.emplace_back(*
this, *BB, Name, SurroundingLoop, Instructions);
2399 auto *Stmt = &
Stmts.back();
2401 for (Instruction *Inst : Instructions) {
2403 "Unexpected statement corresponding to the instruction.");
2409 std::vector<Instruction *> Instructions) {
2410 assert(
R &&
"Unexpected nullptr!");
2411 Stmts.emplace_back(*
this, *
R, Name, SurroundingLoop, Instructions);
2412 auto *Stmt = &
Stmts.back();
2414 for (Instruction *Inst : Instructions) {
2416 "Unexpected statement corresponding to the instruction.");
2420 for (BasicBlock *BB :
R->blocks()) {
2422 if (BB ==
R->getEntry())
2424 for (Instruction &Inst : *BB) {
2426 "Unexpected statement corresponding to the instruction.");
2438 "Target access not defined for complete statement domain");
2440 "Source access not defined for complete statement domain");
2442 Stmts.emplace_back(*
this, SourceRel, TargetRel,
Domain);
2444 return &(
Stmts.back());
2448 auto StmtMapIt =
StmtMap.find(BB);
2449 if (StmtMapIt ==
StmtMap.end())
2451 return StmtMapIt->second;
2455 auto *
PHI = cast<PHINode>(U.getUser());
2456 BasicBlock *IncomingBB =
PHI->getIncomingBlock(U);
2460 if (
auto *IncomingInst = dyn_cast<Instruction>(U.get())) {
2461 if (IncomingInst->getParent() == IncomingBB) {
2463 return IncomingStmt;
2473 if (!StmtList.empty())
2474 return StmtList.back();
2479 if (RN->isSubRegion())
2489 if (!L || !
R.contains(L))
2492 if (
R.isTopLevelRegion()) {
2494 return L->getLoopDepth() - 1;
2496 Loop *OuterLoop =
R.outermostLoopInRegion(
const_cast<Loop *
>(L));
2498 return L->getLoopDepth() - OuterLoop->getLoopDepth();
2503 for (
auto &SAI :
arrays()) {
2504 if (SAI->getName() == BaseName)
2512 assert(SAI &&
"can only use after access relations have been constructed");
2525 llvm::erase(Uses, Access);
2531 llvm::erase(Incomings, Access);
2538 Instruction *Val = dyn_cast<Instruction>(SAI->
getBasePtr());
2572 assert(
contains(Inst) &&
"The concept of escaping makes only sense for "
2573 "values defined inside the SCoP");
2575 for (Use &Use : Inst->uses()) {
2584 isExit(cast<PHINode>(Use.getUser())->getParent()))
2591 AssumptionsAliasing += step;
2596#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
2599 int NumTotalLoops = LoopStat.NumLoops;
2603 for (
const ScopStmt &Stmt : *
this) {
2610 if (MA->isLatestValueKind()) {
2616 if (MA->isLatestAnyPHIKind()) {
2623 MA->getAccessRelation().intersect_domain(
Domain).range();
2647 std::max(MaxNumLoopsInScop.getValue(), (uint64_t)Stats.
NumLoops);
2650 NumScopsDepthZero++;
2656 NumScopsDepthThree++;
2658 NumScopsDepthFour++;
2660 NumScopsDepthFive++;
2662 NumScopsDepthLarger++;
2676 LoopInfo &
LI, AliasAnalysis &
AA, DominatorTree &
DT,
2677 AssumptionCache &
AC, OptimizationRemarkEmitter &
ORE)
2682 if (Inserted &&
SD.isMaxRegionInScop(*R)) {
2685 Scop *
S = It->second.get();
2687#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
2698 return It->second.get();
llvm::cl::OptionCategory PollyCategory
static void updateLoopCountStatistic(ScopDetection::LoopStats Stats, bool OnlyProfitable)
static isl::set simplifyAssumptionContext(isl::set AssumptionContext, const Scop &S)
static isl::set addRangeBoundsToSet(isl::set S, const ConstantRange &Range, int dim, isl::dim type)
static void stretchInnermostSize(SmallVectorImpl< const SCEV * > &Sizes, uint64_t Factor, ScalarEvolution &SE)
Multiply the innermost of Sizes by Factor.
static cl::opt< bool > PollyIgnoreParamBounds("polly-ignore-parameter-bounds", cl::desc("Do not add parameter bounds and do no gist simplify sets accordingly"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
static isl::map getEqualAndLarger(isl::space SetDomain)
static cl::opt< bool > PollyPrintInstructions("polly-print-instructions", cl::desc("Output instructions per ScopStmt"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
static cl::opt< bool > PollyRemarksMinimal("polly-remarks-minimal", cl::desc("Do not emit remarks about assumptions that are known"), cl::Hidden, cl::cat(PollyCategory))
static std::string toString(AssumptionKind Kind)
static cl::opt< bool, true > XUseInstructionNames("polly-use-llvm-names", cl::desc("Use LLVM-IR names when deriving statement names"), cl::location(UseInstructionNames), cl::Hidden, cl::cat(PollyCategory))
static int const MaxDisjunctsInContext
static cl::opt< bool > IslOnErrorAbort("polly-on-isl-error-abort", cl::desc("Abort if an isl error is encountered"), cl::init(true), cl::cat(PollyCategory))
static cl::list< std::string > IslArgs("polly-isl-arg", cl::value_desc("argument"), cl::desc("Option passed to ISL"), cl::cat(PollyCategory))
static cl::opt< bool > PollyPreciseInbounds("polly-precise-inbounds", cl::desc("Take more precise inbounds assumptions (do not scale well)"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
STATISTIC(AssumptionsAliasing, "Number of aliasing assumptions taken.")
static cl::opt< bool > PollyPreciseFoldAccesses("polly-precise-fold-accesses", cl::desc("Fold memory accesses to model more possible delinearizations " "(does not scale well)"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
static int const MaxDisjunktsInDefinedBehaviourContext
static const ScopArrayInfo * identifyBasePtrOriginSAI(Scop *S, Value *BasePtr)
static isl::aff var_on_domain(isl::local_space ls, isl::dim type, unsigned int pos)
static isl::basic_map from_domain_and_range(isl::basic_set domain, isl::basic_set range)
static isl::basic_set universe(isl::space space)
isl::checked::aff div(isl::checked::aff aff2) const
isl::checked::aff pullback(isl::checked::multi_aff ma) const
isl::checked::aff floor() const
isl::checked::aff mod(isl::checked::val mod) const
isl::checked::aff add(isl::checked::aff aff2) const
isl::checked::map detect_equalities() const
isl::checked::map reverse() const
isl::checked::set deltas() const
class size domain_tuple_dim() const
isl::checked::map gist_params(isl::checked::set context) const
isl::checked::set range() const
isl::checked::map gist_domain(isl::checked::set context) const
isl::checked::map coalesce() const
isl::checked::map apply_range(isl::checked::map map2) const
isl::checked::space get_space() const
isl::checked::map apply_domain(isl::checked::map map2) const
isl::checked::map intersect_domain(isl::checked::set set) const
isl::checked::set domain() const
isl::checked::map unite(isl::checked::map map2) const
isl::checked::map intersect_range(isl::checked::set set) const
isl::checked::map lexmin() const
isl::checked::space get_space() const
isl::checked::set le_set(isl::checked::pw_aff pwaff2) const
isl::checked::set lt_set(isl::checked::pw_aff pwaff2) const
boolean is_disjoint(const isl::checked::set &set2) const
isl::checked::set intersect_params(isl::checked::set params) const
isl::checked::set complement() const
isl::checked::set intersect(isl::checked::set set2) const
isl::checked::set gist_params(isl::checked::set context) const
isl::checked::set unite(isl::checked::set set2) const
boolean is_subset(const isl::checked::set &set2) const
class size tuple_dim() const
boolean is_equal(const isl::checked::set &set2) const
isl::checked::space get_space() const
isl::checked::set apply(isl::checked::map map) const
__isl_give isl_set * release()
isl::checked::set params() const
boolean is_singleton() const
__isl_give isl_space * release()
isl::checked::space domain() const
isl::checked::ctx ctx() const
isl::checked::space map_from_set() const
isl::checked::space range() const
isl::checked::union_map unite(isl::checked::union_map umap2) const
isl::checked::union_map intersect_domain(isl::checked::space space) const
isl::checked::union_map coalesce() const
boolean is_subset(const isl::checked::union_set &uset2) const
isl::checked::union_set coalesce() const
isl::checked::union_set intersect(isl::checked::union_set uset2) const
isl::checked::set extract_set(isl::checked::space space) const
isl::checked::val sub(isl::checked::val v2) const
static isl::constraint alloc_inequality(isl::local_space ls)
static isl::constraint alloc_equality(isl::local_space ls)
static isl::id alloc(isl::ctx ctx, const std::string &name, void *user)
static isl::map from_domain_and_range(isl::set domain, isl::set range)
static isl::map from_union_map(isl::union_map umap)
static isl::map from_multi_aff(isl::multi_aff maff)
static isl::map lex_gt(isl::space set_space)
static isl::map from_aff(isl::aff aff)
static isl::map from_pw_aff(isl::pw_aff pwaff)
static isl::map universe(isl::space space)
isl::multi_aff identity() const
static isl::multi_union_pw_aff from_union_map(isl::union_map umap)
static isl::pw_aff var_on_domain(isl::local_space ls, isl::dim type, unsigned int pos)
static isl::pw_multi_aff from_map(isl::map map)
static isl::schedule from_domain(isl::union_set domain)
static isl::set empty(isl::space space)
static isl::set universe(isl::space space)
static isl::space params_alloc(isl::ctx ctx, unsigned int nparam)
static isl::union_map empty(isl::ctx ctx)
Utility proxy to wrap the common members of LoadInst and StoreInst.
Represent memory accesses in statements.
const ScopArrayInfo * getLatestScopArrayInfo() const
Get the ScopArrayInfo object for the base address, or the one set by setNewAccessRelation().
std::string getAccessRelationStr() const
Get an isl string representing the latest access relation.
isl::map getNewAccessRelation() const
Get the new access function imported or set by a pass.
void dump() const
Print the MemoryAccess to stderr.
isl::set assumeNoOutOfBound()
isl::id getArrayId() const
Old name of getOriginalArrayId().
SmallVector< const SCEV *, 4 > Sizes
Size of each dimension of the accessed array.
void foldAccessRelation()
Fold the memory access to consider parametric offsets.
AssertingVH< Value > AccessValue
The value associated with this memory access.
bool isOriginalValueKind() const
Was this MemoryAccess detected as a scalar dependences?
isl::space getOriginalAccessRelationSpace() const
Return the space in which the access relation lives in.
bool isAnyPHIKind() const
Old name of isOriginalAnyPHIKind().
AccessType
The access type of a memory access.
ReductionType
Reduction access type.
@ RT_BOTTOM
Pseudo type for the data flow analysis.
@ RT_NONE
Indicate no reduction at all.
isl::basic_map createBasicAccessMap(ScopStmt *Statement)
SubscriptsTy Subscripts
Subscript expression for each dimension.
isl::map getLatestAccessRelation() const
Return the newest access relation of this access.
isl::id getOriginalArrayId() const
Get the detection-time base array isl::id for this access.
isl::pw_aff getPwAff(const SCEV *E)
Compute the isl representation for the SCEV E wrt.
Instruction * AccessInstruction
The access instruction of this memory access.
void computeBoundsOnAccessRelation(unsigned ElementSize)
Compute bounds on an over approximated access relation.
bool isValueKind() const
Old name of isOriginalValueKind().
bool hasNewAccessRelation() const
Check if a new access relation was imported or set by a pass.
isl::id Id
A unique identifier for this memory access.
bool isWrite() const
Is this a write memory access?
bool IsAffine
Are all the subscripts affine expression?
ReductionType getReductionType() const
Get the reduction type of this access.
const ScopArrayInfo * getOriginalScopArrayInfo() const
Get the detection-time ScopArrayInfo object for the base address.
AssertingVH< Value > BaseAddr
The base address (e.g., A for A[i+j]).
bool isOriginalAnyPHIKind() const
Was this access detected as one of the two PHI types?
void updateDimensionality()
Update the dimensionality of the memory access.
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
bool isStrideZero(isl::map Schedule) const
Is always the same memory accessed for a given statement instance set?
bool isLatestPartialAccess() const
Return whether the MemoryyAccess is a partial access.
std::string getOriginalAccessRelationStr() const
Get an isl string representing the access function read from IR.
isl::set InvalidDomain
The domain under which this access is not modeled precisely.
bool isRead() const
Is this a read memory access?
void buildAccessRelation(const ScopArrayInfo *SAI)
Assemble the access relation from all available information.
isl::id getId() const
Get identifier for the memory access.
isl::map NewAccessRelation
Updated access relation read from JSCOP file.
isl::map getAddressFunction() const
Get an isl map describing the memory address accessed.
void setAccessRelation(isl::map AccessRelation)
Update the original access relation.
bool isMustWrite() const
Is this a must-write memory access?
bool isScalarKind() const
Old name of isOriginalScalarKind.
isl::map AccessRelation
Relation from statement instances to the accessed array elements.
void realignParams()
Align the parameters in the access relation to the scop context.
Type * getElementType() const
Return the element type of the accessed array wrt. this access.
bool isOriginalPHIKind() const
Was this MemoryAccess detected as a special PHI node access?
void print(raw_ostream &OS) const
Print the MemoryAccess.
const ScopArrayInfo * getScopArrayInfo() const
Legacy name of getOriginalScopArrayInfo().
void wrapConstantDimensions()
Carry index overflows of dimensions with constant size to the next higher dimension.
ScopStmt * Statement
Parent ScopStmt of this access.
bool isStrideX(isl::map Schedule, int StrideWidth) const
Is the stride of the access equal to a certain width?
bool isStrideOne(isl::map Schedule) const
Is consecutive memory accessed for a given statement instance set?
Type * ElementType
Type a single array element wrt. this access.
enum AccessType AccType
Whether it a reading or writing access, and if writing, whether it is conditional (MAY_WRITE).
std::string getNewAccessRelationStr() const
Get an isl string representing a new access function, if available.
void buildMemIntrinsicAccessRelation()
Create the access relation for the underlying memory intrinsic.
Value * getOriginalBaseAddr() const
Get the original base address of this access (e.g.
ScopStmt * getStatement() const
Get the statement that contains this memory access.
bool isAffine() const
Is the memory access affine?
isl::set getStride(isl::map Schedule) const
Get the stride of this memory access in the specified Schedule.
bool isMayWrite() const
Is this a may-write memory access?
isl::id getLatestArrayId() const
Get the base array isl::id for this access, modifiable through setNewAccessRelation().
MemoryKind Kind
What is modeled by this MemoryAccess.
isl::pw_multi_aff applyScheduleToAccessRelation(isl::union_map Schedule) const
Return the access relation after the schedule was applied.
MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst, AccessType AccType, Value *BaseAddress, Type *ElemType, bool Affine, ArrayRef< const SCEV * > Subscripts, ArrayRef< const SCEV * > Sizes, Value *AccessValue, MemoryKind Kind)
Create a new MemoryAccess.
std::string getReductionOperatorStr() const
Return a string representation of the access's reduction type.
isl::map getAccessRelation() const
Old name of getLatestAccessRelation().
Value * getAccessValue() const
Return the access value of this memory access.
isl::map getOriginalAccessRelation() const
Get the original access function as read from IR.
void setNewAccessRelation(isl::map NewAccessRelation)
Set the updated access relation read from JSCOP file.
bool isArrayKind() const
Old name of isOriginalArrayKind.
bool isMemoryIntrinsic() const
Is this a memory intrinsic access (memcpy, memset, memmove)?
A class to store information about arrays in the SCoP.
const SCEV * getDimensionSize(unsigned Dim) const
Return the size of dimension dim as SCEV*.
Type * ElementType
The canonical element type of this array.
isl::space getSpace() const
Get the space of this array access.
isl::id Id
The isl id for the base pointer.
SmallVector< isl::pw_aff, 4 > DimensionSizesPw
The sizes of each dimension as isl::pw_aff.
bool isExitPHIKind() const
Is this array info modeling an MemoryKind::ExitPHI?
bool isReadOnly()
If the array is read only.
bool updateSizes(ArrayRef< const SCEV * > Sizes, bool CheckConsistency=true)
Update the sizes of the ScopArrayInfo object.
~ScopArrayInfo()
Destructor to free the isl id of the base pointer.
bool isValueKind() const
Is this array info modeling an llvm::Value?
ScopArrayInfo(Value *BasePtr, Type *ElementType, isl::ctx IslCtx, ArrayRef< const SCEV * > DimensionSizes, MemoryKind Kind, const DataLayout &DL, Scop *S, const char *BaseName=nullptr)
Construct a ScopArrayInfo object.
static const ScopArrayInfo * getFromId(isl::id Id)
Access the ScopArrayInfo associated with an isl Id.
std::string getName() const
Get the name of this memory reference.
bool isPHIKind() const
Is this array info modeling special PHI node memory?
Value * getBasePtr() const
Return the base pointer.
int getElemSizeInBytes() const
Get element size in bytes.
isl::pw_aff getDimensionSizePw(unsigned Dim) const
Return the size of dimension dim as isl::pw_aff.
AssertingVH< Value > BasePtr
The base pointer.
bool isCompatibleWith(const ScopArrayInfo *Array) const
Verify that Array is compatible to this ScopArrayInfo.
void addDerivedSAI(ScopArrayInfo *DerivedSAI)
void updateElementType(Type *NewElementType)
Update the element type of the ScopArrayInfo object.
const ScopArrayInfo * BasePtrOriginSAI
For indirect accesses this is the SAI of the BP origin.
const DataLayout & DL
The data layout of the module.
isl::id getBasePtrId() const
Return the isl id for the base pointer.
Scop & S
The scop this SAI object belongs to.
static const ScopArrayInfo * getFromAccessFunction(isl::pw_multi_aff PMA)
Access the ScopArrayInfo associated with an access function.
unsigned getNumberOfDimensions() const
Return the number of dimensions.
void print(raw_ostream &OS, bool SizeAsPwAff=false) const
Print a readable representation to OS.
Type * getElementType() const
Get the canonical element type of this array.
SmallVector< const SCEV *, 4 > DimensionSizes
The sizes of each dimension as SCEV*.
MemoryKind Kind
The type of this scop array info object.
void dump() const
Dump a readable representation to stderr.
Build the Polly IR (Scop and ScopStmt) on a Region.
std::unique_ptr< Scop > getScop()
Try to build the Polly IR of static control part on the current SESE-Region.
Pass to detect the maximal static control parts (Scops) of a function.
static ScopDetection::LoopStats countBeneficialLoops(Region *R, ScalarEvolution &SE, LoopInfo &LI, unsigned MinProfitableTrips)
Count the number of loops and the maximal loop depth in R.
void invalidate()
Recompute the Scop-Information for a function.
Scop * getScop(const Region *R)
Get the Scop object for the given Region.
OptimizationRemarkEmitter & ORE
ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE, LoopInfo &LI, AAResults &AA, DominatorTree &DT, AssumptionCache &AC, OptimizationRemarkEmitter &ORE)
llvm::SmallDenseMap< const Region *, std::unique_ptr< Scop > > RegionToScopMap
A map of Region to its Scop object containing Polly IR of static control part.
BasicBlock * getEntryBlock() const
Return a BasicBlock from this statement.
void dump() const
Print the ScopStmt to stderr.
bool isEmpty() const
Return true if this statement does not contain any accesses.
std::vector< Instruction * > Instructions
Vector for Instructions in this statement.
void print(raw_ostream &OS, bool PrintInstructions) const
Print the ScopStmt.
Region * R
The region represented by this statement (in the non-affine case).
DenseMap< PHINode *, MemoryAccess * > PHIWrites
Map from PHI nodes to its incoming value when coming from this statement.
isl::set Domain
The iteration domain describes the set of iterations for which this statement is executed.
const std::vector< Instruction * > & getInstructions() const
bool isBlockStmt() const
Return true if this statement represents a single basic block.
void removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting=true)
Remove MA from this statement.
MemoryAccess * ensureValueRead(Value *V)
Check whether there is a value read access for V in this statement, and if not, create one.
Loop * SurroundingLoop
The closest loop that contains this statement.
ScopStmt(Scop &parent, BasicBlock &bb, StringRef Name, Loop *SurroundingLoop, std::vector< Instruction * > Instructions)
Create the ScopStmt from a BasicBlock.
MemoryAccess * lookupInputAccessOf(Value *Val) const
Return the input access of the value, or null if no such MemoryAccess exists.
std::string getScheduleStr() const
Get an isl string representing this schedule.
std::string getDomainStr() const
Get an isl string representing this domain.
void realignParams()
Align the parameters in the statement to the scop context.
void removeAccessData(MemoryAccess *MA)
Remove MA from dictionaries pointing to them.
isl::map getSchedule() const
Get the schedule function of this ScopStmt.
isl::set getInvalidDomain() const
Get the invalid domain for this statement.
SmallVector< Loop *, 4 > NestLoops
DenseMap< const Instruction *, MemoryAccessList > InstructionToAccess
Mapping from instructions to (scalar) memory accesses.
Scop & Parent
Polyhedral description.
void restrictDomain(isl::set NewDomain)
Restrict the domain of the statement.
isl::ctx getIslCtx() const
Get an isl_ctx pointer.
Region * getRegion() const
Get the region represented by this ScopStmt (if any).
DenseMap< Instruction *, MemoryAccess * > ValueWrites
The set of values defined in this ScopStmt that are required elsewhere, mapped to their MemoryKind::V...
BasicBlock * getBasicBlock() const
Get the BasicBlock represented by this ScopStmt (if any).
void removeMemoryAccess(MemoryAccess *MA)
Remove a MemoryAccess from this statement.
MemoryAccessVec MemAccs
The memory accesses of this statement.
const char * getBaseName() const
DenseMap< Value *, MemoryAccess * > ValueReads
The set of values defined elsewhere required in this ScopStmt and their MemoryKind::Value READ Memory...
isl::set InvalidDomain
The domain under which this statement is not modeled precisely.
DenseMap< PHINode *, MemoryAccess * > PHIReads
Map from PHI nodes to its read access in this statement.
isl::id getDomainId() const
Get the id of the iteration domain space.
void addAccess(MemoryAccess *Access, bool Prepend=false)
Add Access to this statement's list of accesses.
bool isRegionStmt() const
Return true if this statement represents a whole region.
void setInvalidDomain(isl::set ID)
Set the invalid context for this statement to ID.
unsigned getNumIterators() const
Loop * getLoopForDimension(unsigned Dimension) const
Get the loop for a dimension.
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
BasicBlock * BB
A SCoP statement represents either a basic block (affine/precise case) or a whole region (non-affine ...
isl::space getDomainSpace() const
Get the space of the iteration domain.
void printInstructions(raw_ostream &OS) const
Print the instructions in ScopStmt.
InvariantEquivClassTy * lookupInvariantEquivClass(Value *Val)
Return the invariant equivalence class for Val if any.
isl::schedule getScheduleTree() const
Get a schedule tree describing the schedule of all statements.
isl::set InvalidContext
The restrictions under which this SCoP was built.
void intersectDefinedBehavior(isl::set Set, AssumptionSign Sign)
Add the conditions from Set (or subtract them if Sign is AS_RESTRICTION) to the defined behaviour con...
isl::space getFullParamSpace() const
Return the full space of parameters.
ArrayRef< MemoryAccess * > getValueUses(const ScopArrayInfo *SAI) const
Return all MemoryAccesses that us an llvm::Value, represented by a ScopArrayInfo.
DenseMap< const ScopArrayInfo *, SmallVector< MemoryAccess *, 4 > > ValueUseAccs
List of all uses (i.e.
isl::union_map getMayWrites()
Get a union map of all may-writes performed in the SCoP.
void printContext(raw_ostream &OS) const
isl::set getInvalidContext() const
Get the invalid context for this Scop.
void dump() const
Print the ScopStmt to stderr.
isl::union_map getSchedule() const
Get the schedule of all the statements in the SCoP.
void invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB=nullptr)
Mark the scop as invalid.
MemoryAccess * getValueDef(const ScopArrayInfo *SAI) const
Return the MemoryAccess that writes an llvm::Value, represented by a ScopArrayInfo.
ScalarEvolution * getSE() const
Return the scalar evolution.
unsigned getMaxLoopDepth() const
Get the maximum depth of the loop.
void printAliasAssumptions(raw_ostream &OS) const
ArrayRef< MemoryAccess * > getPHIIncomings(const ScopArrayInfo *SAI) const
Return all MemoryAccesses for all incoming statements of a PHINode, represented by a ScopArrayInfo.
ScopStmt * getStmtFor(Instruction *Inst) const
Return the ScopStmt an instruction belongs to, or nullptr if it does not belong to any statement in t...
ScopArrayInfo * getScopArrayInfo(Value *BasePtr, MemoryKind Kind)
Return the cached ScopArrayInfo object for BasePtr.
ParameterSetTy Parameters
Parameters of this Scop.
ArrayInfoSetTy ScopArrayInfoSet
A set to remember ScopArrayInfo objects.
ValueToValueMap InvEquivClassVMap
Mapping from invariant loads to the representing invariant load of their equivalence class.
isl::union_map getReads()
Get a union map of all reads performed in the SCoP.
unsigned getCopyStmtsNum()
Get the count of copy statements added to this Scop.
unsigned CopyStmtsNum
Number of copy statements.
DenseMap< BasicBlock *, std::vector< ScopStmt * > > StmtMap
A map from basic blocks to vector of SCoP statements.
void addParams(const ParameterSetTy &NewParameters)
Take a list of parameters and add the new ones to the scop.
isl::set getAssumedContext() const
Get the assumed context for this Scop.
void addScopStmt(BasicBlock *BB, StringRef Name, Loop *SurroundingLoop, std::vector< Instruction * > Instructions)
Create a new SCoP statement for BB.
SCEVAffinator Affinator
The affinator used to translate SCEVs to isl expressions.
ScopArrayInfo * getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, ArrayRef< const SCEV * > Sizes, MemoryKind Kind, const char *BaseName=nullptr)
Return the (possibly new) ScopArrayInfo object for Access.
void addAccessFunction(MemoryAccess *Access)
Add the access function to all MemoryAccess objects of the Scop created in this pass.
isl::schedule Schedule
The schedule of the SCoP.
isl::set getBestKnownDefinedBehaviorContext() const
Return the define behavior context, or if not available, its approximation from all other contexts.
isl::set Context
Constraints on parameters.
isl::union_set getDomains() const
Get a union set containing the iteration domains of all statements.
const BoxedLoopsSetTy & getBoxedLoops() const
Return the set of boxed (thus overapproximated) loops.
std::shared_ptr< isl_ctx > IslCtx
Isl context.
std::string getAssumedContextStr() const
Get an isl string representing the assumed context.
bool isProfitable(bool ScalarsAreUnprofitable) const
Return true if this SCoP can be profitably optimized.
bool isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const
Return true if and only if BB dominates the SCoP.
ScopArrayInfo * getArrayInfoByName(const std::string BaseName)
Find the ScopArrayInfo associated with an isl Id that has name Name.
void addAccessData(MemoryAccess *Access)
Add metadata for Access.
isl::set getDomainConditions(const ScopStmt *Stmt) const
Return the domain of Stmt.
DenseMap< Value *, MemoryAccess * > ValueDefAccs
Map of values to the MemoryAccess that writes its definition.
isl::union_map getMustWrites()
Get a union map of all must-writes performed in the SCoP.
std::pair< std::string, std::string > getEntryExitStr() const
Get the name of the entry and exit blocks of this Scop.
isl::pw_aff getPwAffOnly(const SCEV *E, BasicBlock *BB=nullptr, RecordedAssumptionsTy *RecordedAssumptions=nullptr)
Compute the isl representation for the SCEV E.
ScopStatistics getStatistics() const
Collect statistic about this SCoP.
std::string getContextStr() const
Get an isl string representing the context.
std::pair< MinMaxVectorTy, MinMaxVectorTy > MinMaxVectorPairTy
Pair of minimal/maximal access vectors representing read write and read only accesses.
DenseMap< BasicBlock *, isl::set > DomainMap
A map from basic blocks to their domains.
isl::union_map getAccessesOfType(std::function< bool(MemoryAccess &)> Predicate)
Collect all memory access relations of a given type.
void removeStmts(function_ref< bool(ScopStmt &)> ShouldDelete, bool AfterHoisting=true)
Remove statements from the list of scop statements.
int getRelativeLoopDepth(const Loop *L) const
Get the depth of a loop relative to the outermost loop in the Scop.
isl::ctx getIslCtx() const
Get the isl context of this static control part.
LoopInfo * getLI() const
Return the LoopInfo used for this Scop.
std::string getInvalidContextStr() const
Get an isl string representing the invalid context.
PWACtx getPwAff(const SCEV *E, BasicBlock *BB=nullptr, bool NonNegative=false, RecordedAssumptionsTy *RecordedAssumptions=nullptr, bool IsInsideDomain=true)
Compute the isl representation for the SCEV E.
bool HasSingleExitEdge
True if the underlying region has a single exiting block.
DenseMap< Instruction *, ScopStmt * > InstStmtMap
A map from instructions to SCoP statements.
bool isEscaping(Instruction *Inst)
Return whether Inst has a use outside of this SCoP.
void removeStmtNotInDomainMap()
Removes all statements where the entry block of the statement does not have a corresponding domain in...
ScopDetection::DetectionContext & DC
The context of the SCoP created during SCoP detection.
void print(raw_ostream &OS, bool PrintInstructions) const
Print the static control part.
void printStatements(raw_ostream &OS, bool PrintInstructions) const
isl::union_map getWrites()
Get a union map of all writes performed in the SCoP.
void setSchedule(isl::union_map NewSchedule)
Update the current schedule.
void setContext(isl::set NewContext)
Set new isl context.
bool hasFeasibleRuntimeContext() const
Return true if the optimized SCoP can be executed.
DenseMap< const SCEV *, isl::id > ParameterIds
Mapping from parameters to their ids.
isl::space getParamSpace() const
Return space of isl context parameters.
bool isExit(BasicBlock *BB) const
Return true if BB is the exit block of the SCoP.
std::string getNameStr() const
Get the name of this Scop.
DenseMap< PHINode *, MemoryAccess * > PHIReadAccs
Map of values to the MemoryAccess that reads a PHI.
static void incrementNumberOfAliasingAssumptions(unsigned Step)
Increment actual number of aliasing assumptions taken.
std::pair< isl::pw_multi_aff, isl::pw_multi_aff > MinMaxAccessTy
Type to represent a pair of minimal/maximal access to an array.
std::optional< std::string > name
The name of the SCoP (identical to the regions name)
void createParameterId(const SCEV *Param)
Create an id for Param and store it in the ParameterIds map.
ArrayNameMapTy ScopArrayNameMap
A map to remember ScopArrayInfo objects for all names of memory references.
isl::set DefinedBehaviorContext
The context under which the SCoP must have defined behavior.
bool isEmpty() const
Return whether this scop is empty, i.e.
DenseMap< const ScopArrayInfo *, SmallVector< MemoryAccess *, 4 > > PHIIncomingAccs
List of all incoming values (write MemoryAccess) of a MemoryKind::PHI or MemoryKind::ExitPHI scalar.
isl::id getIdForParam(const SCEV *Parameter) const
Return the isl_id that represents a certain parameter.
InvariantEquivClassesTy InvariantEquivClasses
List of invariant accesses.
BasicBlock * getExitingBlock() const
Return the unique exiting block of the SCoP if any.
Region & R
The underlying Region.
OptimizationRemarkEmitter & ORE
OptimizationRemarkEmitter object for displaying diagnostic remarks.
bool ScheduleModified
Whether the schedule has been modified after derived from the CFG by ScopBuilder.
size_t getNumParams() const
Get the count of parameters used in this Scop.
void addParameterBounds()
Add the bounds of the parameters to the context.
bool restrictDomains(isl::union_set Domain)
Intersects the domains of all statements in the SCoP.
isl::union_map getAccesses()
Get a union map of all memory accesses performed in the SCoP.
ScopArrayInfo * createScopArrayInfo(Type *ElementType, const std::string &BaseName, const std::vector< unsigned > &Sizes)
Create an array and return the corresponding ScopArrayInfo object.
StmtSet Stmts
The statements in this Scop.
void removeAccessData(MemoryAccess *Access)
Remove the metadata stored for Access.
ArrayRef< ScopStmt * > getStmtListFor(BasicBlock *BB) const
Return the list of ScopStmts that represent the given BB.
MemoryAccess * getPHIRead(const ScopArrayInfo *SAI) const
Return the MemoryAccess that represents an llvm::PHINode.
bool contains(const Loop *L) const
Check if L is contained in the SCoP.
static std::unique_ptr< Scop > makeScop(Region &R, ScalarEvolution &SE, LoopInfo &LI, DominatorTree &DT, ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE, int ID)
Factory pattern for creating a new (empty) SCoP.
void realignParams()
Align the parameters in the statement to the scop context.
Function & getFunction() const
Return the function this SCoP is in.
ArrayInfoMapTy ScopArrayInfoMap
A map to remember ScopArrayInfo objects for all base pointers.
void printArrayInfo(raw_ostream &OS) const
Scop(Region &R, ScalarEvolution &SE, LoopInfo &LI, DominatorTree &DT, ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE, int ID)
Scop constructor; invoked from ScopBuilder::buildScop.
const SCEV * getRepresentingInvariantLoadSCEV(const SCEV *S) const
Get the representing SCEV for S if applicable, otherwise S.
void simplifyContexts()
Simplify the assumed and invalid context.
bool hasSingleExitEdge() const
Return true if the underlying region has a single exiting block.
ScopArrayInfo * getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind)
Return the cached ScopArrayInfo object for BasePtr.
MemoryAccess * lookupBasePtrAccess(MemoryAccess *MA)
Return the access for the base ptr of MA if any.
isl::set AssumedContext
The assumptions under which this scop was built.
void addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB, bool RTC=true)
Add assumptions to assumed context.
MinMaxVectorPairVectorTy MinMaxAliasGroups
The set of minimal/maximal accesses for each alias group.
bool isEffectiveAssumption(isl::set Set, AssumptionSign Sign)
Check if the assumption in Set is trivial or not.
void simplifySCoP(bool AfterHoisting)
Simplify the SCoP representation.
ScopStmt * getIncomingStmtFor(const Use &U) const
Get the statement to put a PHI WRITE into.
bool trackAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB)
Track and report an assumption.
isl::set getContext() const
Get the constraint on parameter of this Scop.
void setScheduleTree(isl::schedule NewSchedule)
Update the current schedule.
BasicBlock * getEntry() const
Return the unique entry block of the SCoP.
const int ID
A number that uniquely represents a Scop within its function.
ScopStmt * getLastStmtFor(BasicBlock *BB) const
Return the last statement representing BB.
void removeFromStmtMap(ScopStmt &Stmt)
Removes Stmt from the StmtMap.
isl_ctx * isl_ctx_alloc(void)
int isl_ctx_parse_options(isl_ctx *ctx, int argc, char **argv, unsigned flags)
void isl_ctx_free(isl_ctx *ctx)
boolean manage(isl_bool val)
std::forward_list< MemoryAccess * > MemoryAccessList
Ordered list type to hold accesses.
std::pair< isl::pw_aff, isl::set > PWACtx
The result type of the SCEVAffinator.
unsigned const MaxDisjunctsInDomain
std::string getIslCompatibleName(const std::string &Prefix, const llvm::Value *Val, long Number, const std::string &Suffix, bool UseInstructionNames)
Combine Prefix, Val (or Number) and Suffix to an isl-compatible name.
llvm::SetVector< const llvm::SCEV * > ParameterSetTy
Set type for parameters.
AssumptionSign
Enum to distinguish between assumptions and restrictions.
MemoryKind
The different memory kinds used in Polly.
@ Array
MemoryKind::Array: Models a one or multi-dimensional array.
@ Value
MemoryKind::Value: Models an llvm::Value.
@ PHI
MemoryKind::PHI: Models PHI nodes within the SCoP.
raw_ostream & operator<<(raw_ostream &OS, MemoryAccess::ReductionType RT)
isl::val getConstant(isl::pw_aff PwAff, bool Max, bool Min)
If PwAff maps to a constant, return said constant.
bool hasDebugCall(ScopStmt *Stmt)
Does the statement contain a call to a debug function?
llvm::BasicBlock * getUseBlock(const llvm::Use &U)
Return the block in which a value is used.
isl::val valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int, bool IsSigned)
Translate an llvm::APInt to an isl::val.
void simplify(isl::set &Set)
Simplify a set inplace.
bool PollyProcessUnprofitable
std::pair< const llvm::SCEVConstant *, const llvm::SCEV * > extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE)
Extract the constant factors from the multiplication M.
llvm::SmallVector< Assumption, 8 > RecordedAssumptionsTy
AssumptionKind
Enumeration of assumptions Polly can take.
isl_stat isl_options_set_on_error(isl_ctx *ctx, int val)
#define ISL_ON_ERROR_ABORT
isl_stat isl_options_set_schedule_serialize_sccs(isl_ctx *ctx, int val)
__isl_give isl_space * isl_space_params_alloc(isl_ctx *ctx, unsigned nparam)
Type for equivalent invariant accesses and their domain context.
Context variables for SCoP detection.
Helper data structure to collect statistics about loop counts.
int NumValueWritesInLoops
int NumSingletonWritesInLoops
static TupleKindPtr Domain("Domain")
static TupleKindPtr Range("Range")
__isl_give isl_union_set * isl_union_set_add_set(__isl_take isl_union_set *uset, __isl_take isl_set *set)
__isl_give isl_union_set * isl_union_set_empty(__isl_take isl_space *space)