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"),
161 "polly-print-instructions", cl::desc(
"Output instructions per ScopStmt"),
162 cl::Hidden, cl::Optional, cl::init(
false), cl::cat(
PollyCategory));
164static cl::list<std::string>
IslArgs(
"polly-isl-arg",
165 cl::value_desc(
"argument"),
166 cl::desc(
"Option passed to ISL"),
180 S =
S.lower_bound_val(
type, dim, V);
182 S =
S.upper_bound_val(
type, dim, V);
184 if (
Range.isFullSet())
192 if (
Range.isSignWrappedSet()) {
206 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr);
210 if (!
S->contains(BasePtrLI))
213 ScalarEvolution &SE = *
S->getSE();
215 const SCEV *OriginBaseSCEV =
216 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand()));
220 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV);
221 if (!OriginBaseSCEVUnknown)
224 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(),
231 const char *BaseName)
233 std::string BasePtrName =
286 auto OldElementSize =
DL.getTypeAllocSizeInBits(
ElementType);
287 auto NewElementSize =
DL.getTypeAllocSizeInBits(NewElementType);
289 if (NewElementSize == OldElementSize || NewElementSize == 0)
292 if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) {
295 auto GCD = std::gcd((uint64_t)NewElementSize, (uint64_t)OldElementSize);
301 bool CheckConsistency) {
302 int SharedDims = std::min(NewSizes.size(),
DimensionSizes.size());
303 int ExtraDimsNew = NewSizes.size() - SharedDims;
306 if (CheckConsistency) {
307 for (
int i = 0; i < SharedDims; i++) {
308 auto *NewSize = NewSizes[i + ExtraDimsNew];
310 if (NewSize && KnownSize && NewSize != KnownSize)
341#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
358 OS <<
" " << Size <<
" ";
377 assert(!
Id.is_null() &&
"Output dimension didn't have an ID");
382 void *User =
Id.get_user();
391 unsigned DimsArray = SAI->getNumberOfDimensions();
394 ArraySpace.map_from_domain_and_range(ArraySpace));
398 for (
int i = DimsArray - 1; i > 0; i--) {
399 auto *DimSize = SAI->getDimensionSize(i);
400 auto *DimSizeCst = dyn_cast<SCEVConstant>(DimSize);
407 if (DimSize->isZero())
419 Modulo = Modulo.
pullback(DivModAff);
423 Divide = Divide.
floor();
424 Divide = Divide.
add(PrevVar);
425 Divide = Divide.
pullback(DivModAff);
428 DivModAff = DivModAff.set_aff(i, Modulo);
429 DivModAff = DivModAff.set_aff(i - 1, Divide);
447 assert(DimsArray >= DimsAccess);
448 unsigned DimsMissing = DimsArray - DimsAccess;
451 auto &DL = BB->getModule()->getDataLayout();
452 unsigned ArrayElemSize = SAI->getElemSizeInBytes();
458 for (
auto i : seq<unsigned>(0, DimsMissing))
461 for (
auto i : seq<unsigned>(DimsMissing, DimsArray))
476 if (DimsAccess == 1) {
497 if (ElemBytes > ArrayElemSize) {
498 assert(ElemBytes % ArrayElemSize == 0 &&
499 "Loaded element size should be multiple of canonical element size");
503 for (
auto i : seq<unsigned>(0, DimsArray - 1))
516 Map = Map.add_constraint(
C);
522 Map = Map.add_constraint(
C);
531 llvm_unreachable(
"Requested a reduction operator string for a memory "
532 "access which isn't a reduction");
534 llvm_unreachable(
"Requested a reduction operator string for a internal "
547 llvm_unreachable(
"Unknown reduction type");
552 void *User = ArrayId.get_user();
559 void *User = ArrayId.get_user();
616 Space = Space.align_params(
Statement->getDomainSpace());
659 Outside = Outside.
unite(DimOutside);
664 Outside = Outside.
params();
670 Outside = Outside.remove_divs();
695 LengthMap = LengthMap.align_params(SubscriptMap.
get_space());
696 SubscriptMap = SubscriptMap.align_params(LengthMap.
get_space());
697 LengthMap = LengthMap.sum(SubscriptMap);
703 ScalarEvolution *SE =
Statement->getParent()->getSE();
706 if (isa<MemIntrinsic>(MAI))
709 Value *Ptr = MAI.getPointerOperand();
710 if (!Ptr || !SE->isSCEVable(Ptr->getType()))
713 const SCEV *PtrSCEV = SE->getSCEV(Ptr);
714 if (isa<SCEVCouldNotCompute>(PtrSCEV))
717 const SCEV *BasePtrSCEV = SE->getPointerBase(PtrSCEV);
718 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV))
719 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV);
721 const ConstantRange &
Range = SE->getSignedRange(PtrSCEV);
722 if (
Range.isFullSet())
725 if (
Range.isUpperWrapped() ||
Range.isSignWrappedSet())
728 bool isWrapping =
Range.isSignWrappedSet();
730 unsigned BW =
Range.getBitWidth();
731 const auto One = APInt(BW, 1);
732 const auto LB = isWrapping ?
Range.getLower() :
Range.getSignedMin();
733 const auto UB = isWrapping ? (
Range.getUpper() - One) :
Range.getSignedMax();
735 auto Min = LB.sdiv(APInt(BW, ElementSize));
736 auto Max = UB.sdiv(APInt(BW, ElementSize)) + One;
738 assert(Min.sle(Max) &&
"Minimum expected to be less or equal than max");
748 if (
Sizes.size() < 2 || isa<SCEVConstant>(
Sizes[1]))
755 for (
int i = Size - 2; i >= 0; --i) {
765 Space = Space.align_params(SpaceSize);
770 for (
int j = 0; j < Size; ++j)
775 for (
int j = 0; j < Size; ++j)
776 if (j < i || j > i + 1)
782 C =
C.set_constant_si(-1);
785 MapTwo = MapTwo.add_constraint(
C);
790 MapTwo = MapTwo.add_constraint(
C);
791 MapTwo = MapTwo.upper_bound_si(
isl::dim::in, i + 1, -1);
793 MapOne = MapOne.
unite(MapTwo);
846 for (
int i = 0, Size =
Subscripts.size(); i < Size; ++i) {
872 static const std::string TypeStrings[] = {
"",
"_Read",
"_Write",
"_MayWrite"};
873 const std::string Access = TypeStrings[
AccType] + utostr(Stmt->
size());
884 Sizes.push_back(
nullptr);
885 for (
unsigned i = 1; i < SAI->getNumberOfDimensions(); i++)
886 Sizes.push_back(SAI->getDimensionSize(i));
889 static const std::string TypeStrings[] = {
"",
"_Read",
"_Write",
"_MayWrite"};
890 const std::string Access = TypeStrings[
AccType] + utostr(Stmt->
size());
933 OS.indent(12) <<
"ReadAccess :=\t";
936 OS.indent(12) <<
"MustWriteAccess :=\t";
939 OS.indent(12) <<
"MayWriteAccess :=\t";
951#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
957 PWACtx PWAC = Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock());
959 StmtDom = StmtDom.reset_tuple_id();
986 for (
unsigned i = 0; i < lastDimension; ++i)
1002 Schedule = Schedule.
reverse();
1003 NextScatt = NextScatt.
lexmin();
1021 for (
auto i : seq<int>(0, Size - 1))
1023 StrideX = StrideX.fix_si(
isl::dim::set, Size - 1, StrideWidth);
1049 assert(OriginalDomainSpace.has_equal_tuples(NewDomainSpace));
1061 "Partial READ accesses not supported");
1066 "Must specify the array that is accessed");
1068 auto *SAI =
static_cast<ScopArrayInfo *
>(NewArrayId.get_user());
1069 assert(SAI &&
"Must set a ScopArrayInfo");
1071 if (SAI->isArrayKind() && SAI->getBasePtrOriginSAI()) {
1076 "Access functions to indirect arrays must have an invariant and "
1077 "hoisted base pointer");
1082 unsigned Dims = SAI->getNumberOfDimensions();
1084 assert(SpaceSize == Dims &&
"Access dims must match array dims");
1106 if (Schedule.is_null())
1109 if (Schedule.is_empty())
1111 isl::map M = M.from_union_map(Schedule);
1120 "New domain is not a subset of old domain!");
1129 MAL.emplace_front(Access);
1131 Instruction *AccessVal = cast<Instruction>(Access->
getAccessValue());
1179 std::vector<Instruction *> EntryBlockInstructions)
1241 OS <<
"Instructions {\n";
1244 OS.indent(16) << *Inst <<
"\n";
1246 OS.indent(12) <<
"}\n";
1251 OS.indent(12) <<
"Domain :=\n";
1256 OS.indent(16) <<
"n/a\n";
1258 OS.indent(12) <<
"Schedule :=\n";
1263 OS.indent(16) <<
"n/a\n";
1268 if (PrintInstructions)
1272#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1280 assert(Found &&
"Expected access data not found");
1285 assert(Found &&
"Expected access data not found");
1290 assert(Found &&
"Expected access data not found");
1295 assert(Found &&
"Expected access data not found");
1310 if (Predicate(MA)) {
1312 Parent.removeAccessData(MA);
1315 llvm::erase_if(
MemAccs, Predicate);
1320 if (AfterHoisting) {
1326 Parent.removeAccessData(MA);
1331 It->second.remove(MA);
1332 if (It->second.empty())
1346 Parent.addAccessFunction(Access);
1349 Parent.addAccessData(Access);
1368class SCEVSensitiveParameterRewriter final
1369 :
public SCEVRewriteVisitor<SCEVSensitiveParameterRewriter> {
1370 const ValueToValueMap &VMap;
1373 SCEVSensitiveParameterRewriter(
const ValueToValueMap &VMap,
1374 ScalarEvolution &SE)
1375 : SCEVRewriteVisitor(SE), VMap(VMap) {}
1377 static const SCEV *rewrite(
const SCEV *E, ScalarEvolution &SE,
1378 const ValueToValueMap &VMap) {
1379 SCEVSensitiveParameterRewriter SSPR(VMap, SE);
1380 return SSPR.visit(E);
1383 const SCEV *visitAddRecExpr(
const SCEVAddRecExpr *E) {
1384 const SCEV *Start = visit(E->getStart());
1385 const SCEV *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0),
1386 visit(E->getStepRecurrence(SE)),
1387 E->getLoop(), SCEV::FlagAnyWrap);
1388 return SE.getAddExpr(Start, AddRec);
1391 const SCEV *visitUnknown(
const SCEVUnknown *E) {
1392 if (
auto *NewValue = VMap.lookup(E->getValue()))
1393 return SE.getUnknown(NewValue);
1399class SCEVFindInsideScop :
public SCEVTraversal<SCEVFindInsideScop> {
1400 const ValueToValueMap &VMap;
1401 bool FoundInside =
false;
1405 SCEVFindInsideScop(
const ValueToValueMap &VMap, ScalarEvolution &SE,
1407 : SCEVTraversal(*this), VMap(VMap),
S(
S) {}
1409 static bool hasVariant(
const SCEV *E, ScalarEvolution &SE,
1410 const ValueToValueMap &VMap,
const Scop *
S) {
1411 SCEVFindInsideScop SFIS(VMap, SE,
S);
1413 return SFIS.FoundInside;
1416 bool follow(
const SCEV *E) {
1417 if (
auto *AddRec = dyn_cast<SCEVAddRecExpr>(E)) {
1418 FoundInside |=
S->getRegion().contains(AddRec->getLoop());
1419 }
else if (
auto *Unknown = dyn_cast<SCEVUnknown>(E)) {
1420 if (Instruction *I = dyn_cast<Instruction>(Unknown->getValue()))
1421 FoundInside |=
S->getRegion().contains(I) && !VMap.count(I);
1423 return !FoundInside;
1426 bool isDone() {
return FoundInside; }
1445 std::string ParameterName =
"p_" + std::to_string(
getNumParams() - 1);
1447 if (
const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
1448 Value *Val = ValueParameter->getValue();
1455 ParameterName = Val->getName().str();
1456 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) {
1457 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets();
1458 if (LoadOrigin->hasName()) {
1459 ParameterName +=
"_loaded_from_";
1461 LI->getPointerOperand()->stripInBoundsOffsets()->getName();
1470 const_cast<void *
>((
const void *)Parameter));
1475 for (
const SCEV *Parameter : NewParameters) {
1498 ConstantRange SRange =
SE->getSignedRange(Parameter);
1537 if (!
S.hasErrorBlock()) {
1538 auto DomainParameters =
S.getDomains().params();
1539 AssumptionContext = AssumptionContext.
gist_params(DomainParameters);
1542 AssumptionContext = AssumptionContext.
gist_params(
S.getContext());
1543 return AssumptionContext;
1588 return DIt->getSecond();
1590 auto &RI = *
R.getRegionInfo();
1591 auto *BBR = RI.getRegionFor(BB);
1592 while (BBR->getEntry() == BB)
1593 BBR = BBR->getParent();
1599 OptimizationRemarkEmitter &
ORE,
int ID)
1607 SmallVector<char *, 8> IslArgv;
1608 IslArgv.reserve(1 +
IslArgs.size());
1611 IslArgv.push_back(
const_cast<char *
>(
"-polly-isl-arg"));
1613 for (std::string &Arg :
IslArgs)
1614 IslArgv.push_back(
const_cast<char *
>(Arg.c_str()));
1635 LoopInfo &LI, DominatorTree &
DT,
1637 OptimizationRemarkEmitter &
ORE,
int ID) {
1648 for (BasicBlock *BB : Stmt.
getRegion()->blocks()) {
1654 for (Instruction &Inst : *BB)
1659 if (StmtMapIt !=
StmtMap.end())
1660 llvm::erase(StmtMapIt->second, &Stmt);
1667 bool AfterHoisting) {
1668 for (
auto StmtIt =
Stmts.begin(), StmtEnd =
Stmts.end(); StmtIt != StmtEnd;) {
1669 if (!ShouldDelete(*StmtIt)) {
1677 SmallVector<MemoryAccess *, 16> MAList(StmtIt->begin(), StmtIt->end());
1679 StmtIt->removeSingleMemoryAccess(MA, AfterHoisting);
1682 StmtIt =
Stmts.erase(StmtIt);
1691 return Domain.is_empty();
1697 [AfterHoisting](
ScopStmt &Stmt) ->
bool {
1702 bool RemoveStmt = Stmt.
isEmpty();
1705 if (!RemoveStmt && AfterHoisting) {
1706 bool OnlyRead =
true;
1715 RemoveStmt = OnlyRead;
1723 LoadInst *LInst = dyn_cast<LoadInst>(Val);
1728 LInst = cast<LoadInst>(Rep);
1730 Type *Ty = LInst->getType();
1731 const SCEV *PointerSCEV =
SE->getSCEV(LInst->getPointerOperand());
1733 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
1736 auto &MAs = IAClass.InvariantAccesses;
1737 for (
auto *MA : MAs)
1738 if (MA->getAccessInstruction() == Val)
1746 ArrayRef<const SCEV *> Sizes,
1748 const char *BaseName) {
1749 assert((BasePtr || BaseName) &&
1750 "BasePtr and BaseName can not be nullptr at the same time.");
1751 assert(!(BasePtr && BaseName) &&
"BaseName is redundant.");
1755 auto &DL =
getFunction().getParent()->getDataLayout();
1757 DL,
this, BaseName));
1760 SAI->updateElementType(ElementType);
1763 if (!SAI->updateSizes(Sizes))
1770 const std::string &BaseName,
1771 const std::vector<unsigned> &Sizes) {
1773 std::vector<const SCEV *> SCEVSizes;
1775 for (
auto size : Sizes)
1779 SCEVSizes.push_back(
nullptr);
1793 assert(SAI &&
"No ScopArrayInfo available for this base pointer");
1811 std::string ExitName, EntryName;
1813 return EntryName +
"---" + ExitName;
1817 std::string ExitName, EntryName;
1818 raw_string_ostream ExitStr(ExitName);
1819 raw_string_ostream EntryStr(EntryName);
1821 R.getEntry()->printAsOperand(EntryStr,
false);
1824 R.getExit()->printAsOperand(ExitStr,
false);
1826 ExitName =
"FunctionExit";
1828 return std::make_pair(EntryName, ExitName);
1860 unsigned OptimizableStmtsOrLoops = 0;
1861 for (
auto &Stmt : *
this) {
1862 if (Stmt.getNumIterators() == 0)
1865 bool ContainsArrayAccs =
false;
1866 bool ContainsScalarAccs =
false;
1867 for (
auto *MA : Stmt) {
1870 ContainsArrayAccs |= MA->isLatestArrayKind();
1871 ContainsScalarAccs |= MA->isLatestScalarKind();
1874 if (!ScalarsAreUnprofitable || (ContainsArrayAccs && !ContainsScalarAccs))
1875 OptimizableStmtsOrLoops += Stmt.getNumIterators();
1878 return OptimizableStmtsOrLoops > 1;
1896 auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase);
1897 if (!PointerBaseInst)
1900 auto *BasePtrStmt =
getStmtFor(PointerBaseInst);
1904 return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst);
1910 return "No-aliasing";
1914 return "No-overflows";
1916 return "Signed-unsigned";
1918 return "Low complexity";
1920 return "Profitable";
1924 return "Finite loop";
1926 return "Invariant load";
1928 return "Delinearization";
1930 llvm_unreachable(
"Unknown AssumptionKind!");
1970 AssumptionsAliasing++;
1973 AssumptionsInbounds++;
1976 AssumptionsWrapping++;
1979 AssumptionsUnsigned++;
1982 AssumptionsComplexity++;
1985 AssumptionsUnprofitable++;
1988 AssumptionsErrorBlock++;
1991 AssumptionsInfiniteLoop++;
1994 AssumptionsInvariantLoad++;
1997 AssumptionsDelinearization++;
2001 auto Suffix = Sign ==
AS_ASSUMPTION ?
" assumption:\t" :
" restriction:\t";
2002 std::string Msg =
toString(
Kind) + Suffix + stringFromIslObj(Set);
2004 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"AssumpRestrict", Loc, BB)
2007 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"AssumpRestrict", Loc,
2053 POLLY_DEBUG(dbgs() <<
"Invalidate SCoP because of reason " <<
Kind <<
"\n");
2061 OS.indent(4) <<
Context <<
"\n";
2063 OS.indent(4) <<
"Assumed Context:\n";
2066 OS.indent(4) <<
"Invalid Context:\n";
2069 OS.indent(4) <<
"Defined Behavior Context:\n";
2073 OS.indent(4) <<
"<unavailable>\n";
2077 OS.indent(4) <<
"p" << Dim++ <<
": " << *Parameter <<
"\n";
2083 if (
Pair.second.size() == 0)
2086 noOfGroups +=
Pair.second.size();
2089 OS.indent(4) <<
"Alias Groups (" << noOfGroups <<
"):\n";
2091 OS.indent(8) <<
"n/a\n";
2098 if (
Pair.second.empty()) {
2099 OS.indent(8) <<
"[[";
2101 OS <<
" <" << MMANonReadOnly.first <<
", " << MMANonReadOnly.second
2108 OS.indent(8) <<
"[[";
2109 OS <<
" <" << MMAReadOnly.first <<
", " << MMAReadOnly.second <<
">";
2111 OS <<
" <" << MMANonReadOnly.first <<
", " << MMANonReadOnly.second
2120 OS <<
"Statements {\n";
2122 for (
const ScopStmt &Stmt : *
this) {
2124 Stmt.
print(OS, PrintInstructions);
2127 OS.indent(4) <<
"}\n";
2136 OS.indent(4) <<
"}\n";
2138 OS.indent(4) <<
"Arrays (Bounds as pw_affs) {\n";
2141 Array->print(OS,
true);
2143 OS.indent(4) <<
"}\n";
2147 OS.indent(4) <<
"Function: " <<
getFunction().getName() <<
"\n";
2148 OS.indent(4) <<
"Region: " <<
getNameStr() <<
"\n";
2150 OS.indent(4) <<
"Invariant Accesses: {\n";
2152 const auto &MAs = IAClass.InvariantAccesses;
2154 OS.indent(12) <<
"Class Pointer: " << *IAClass.IdentifyingPointer <<
"\n";
2156 MAs.front()->print(OS);
2157 OS.indent(12) <<
"Execution Context: " << IAClass.ExecutionContext
2161 OS.indent(4) <<
"}\n";
2168#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2177 bool IsInsideDomain) {
2183 PWACtx PWAC =
Affinator.getPwAff(E, BB, RecordedAssumptions, IsInsideDomain);
2184 if (!PWAC.first.is_null()) {
2191 Affinator.takeNonNegativeAssumption(PWAC, RecordedAssumptions);
2195 auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
2197 return Affinator.getPwAff(
SE->getZero(E->getType()), BB, RecordedAssumptions);
2222 if (!Predicate(*MA))
2226 isl::map AccessDomain = MA->getAccessRelation();
2228 Accesses = Accesses.
unite(AccessDomain);
2262 return Tree.get_map();
2282 bool Changed =
false;
2287 if (StmtDomain.
is_subset(NewStmtDomain))
2292 NewStmtDomain = NewStmtDomain.
coalesce();
2305 std::vector<Instruction *> Instructions) {
2306 assert(BB &&
"Unexpected nullptr!");
2307 Stmts.emplace_back(*
this, *BB, Name, SurroundingLoop, Instructions);
2308 auto *Stmt = &
Stmts.back();
2310 for (Instruction *Inst : Instructions) {
2312 "Unexpected statement corresponding to the instruction.");
2318 std::vector<Instruction *> Instructions) {
2319 assert(
R &&
"Unexpected nullptr!");
2320 Stmts.emplace_back(*
this, *
R, Name, SurroundingLoop, Instructions);
2321 auto *Stmt = &
Stmts.back();
2323 for (Instruction *Inst : Instructions) {
2325 "Unexpected statement corresponding to the instruction.");
2329 for (BasicBlock *BB :
R->blocks()) {
2331 if (BB ==
R->getEntry())
2333 for (Instruction &Inst : *BB) {
2335 "Unexpected statement corresponding to the instruction.");
2347 "Target access not defined for complete statement domain");
2349 "Source access not defined for complete statement domain");
2351 Stmts.emplace_back(*
this, SourceRel, TargetRel,
Domain);
2353 return &(
Stmts.back());
2357 auto StmtMapIt =
StmtMap.find(BB);
2358 if (StmtMapIt ==
StmtMap.end())
2360 return StmtMapIt->second;
2364 auto *
PHI = cast<PHINode>(U.getUser());
2365 BasicBlock *IncomingBB =
PHI->getIncomingBlock(U);
2369 if (
auto *IncomingInst = dyn_cast<Instruction>(U.get())) {
2370 if (IncomingInst->getParent() == IncomingBB) {
2372 return IncomingStmt;
2382 if (!StmtList.empty())
2383 return StmtList.back();
2388 if (RN->isSubRegion())
2398 if (!L || !
R.contains(L))
2401 if (
R.isTopLevelRegion()) {
2403 return L->getLoopDepth() - 1;
2405 Loop *OuterLoop =
R.outermostLoopInRegion(
const_cast<Loop *
>(L));
2407 return L->getLoopDepth() - OuterLoop->getLoopDepth();
2412 for (
auto &SAI :
arrays()) {
2413 if (SAI->getName() == BaseName)
2421 assert(SAI &&
"can only use after access relations have been constructed");
2434 llvm::erase(Uses, Access);
2440 llvm::erase(Incomings, Access);
2447 Instruction *Val = dyn_cast<Instruction>(SAI->
getBasePtr());
2481 assert(
contains(Inst) &&
"The concept of escaping makes only sense for "
2482 "values defined inside the SCoP");
2484 for (Use &Use : Inst->uses()) {
2493 isExit(cast<PHINode>(Use.getUser())->getParent()))
2500 AssumptionsAliasing += step;
2505#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
2508 int NumTotalLoops = LoopStat.NumLoops;
2512 for (
const ScopStmt &Stmt : *
this) {
2519 if (MA->isLatestValueKind()) {
2525 if (MA->isLatestAnyPHIKind()) {
2532 MA->getAccessRelation().intersect_domain(
Domain).range();
2556 std::max(MaxNumLoopsInScop.getValue(), (uint64_t)Stats.
NumLoops);
2559 NumScopsDepthZero++;
2565 NumScopsDepthThree++;
2567 NumScopsDepthFour++;
2569 NumScopsDepthFive++;
2571 NumScopsDepthLarger++;
2585 LoopInfo &
LI, AliasAnalysis &
AA, DominatorTree &
DT,
2586 AssumptionCache &
AC, OptimizationRemarkEmitter &
ORE)
2591 if (Inserted &&
SD.isMaxRegionInScop(*R)) {
2594 Scop *
S = It->second.get();
2596#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
2607 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 cl::opt< bool > PollyPrintInstructions("polly-print-instructions", cl::desc("Output instructions per ScopStmt"), cl::Hidden, cl::Optional, cl::init(false), cl::cat(PollyCategory))
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 > 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)