24#include "llvm/ADT/Statistic.h"
25#include "llvm/IR/Module.h"
28#define DEBUG_TYPE "polly-delicm"
35static cl::opt<bool> PollyPrintDeLICM(
"polly-print-delicm",
36 cl::desc(
"Polly - Print DeLICM/DePRE"),
40 DelicmMaxOps(
"polly-delicm-max-ops",
41 cl::desc(
"Maximum number of isl operations to invest for "
42 "lifetime analysis; 0=no limit"),
45cl::opt<bool> DelicmOverapproximateWrites(
46 "polly-delicm-overapproximate-writes",
48 "Do more PHI writes than necessary in order to avoid partial accesses"),
51cl::opt<bool> DelicmPartialWrites(
"polly-delicm-partial-writes",
52 cl::desc(
"Allow partial writes"),
53 cl::init(
true), cl::Hidden,
57 DelicmComputeKnown(
"polly-delicm-compute-known",
58 cl::desc(
"Compute known content of array elements"),
61STATISTIC(DeLICMAnalyzed,
"Number of successfully analyzed SCoPs");
63 "Analyses aborted because max_operations was reached");
64STATISTIC(MappedValueScalars,
"Number of mapped Value scalars");
65STATISTIC(MappedPHIScalars,
"Number of mapped PHI scalars");
66STATISTIC(TargetsMapped,
"Number of stores used for at least one mapping");
67STATISTIC(DeLICMScopsModified,
"Number of SCoPs optimized");
69STATISTIC(NumValueWrites,
"Number of scalar value writes after DeLICM");
71 "Number of scalar value writes nested in affine loops after DeLICM");
72STATISTIC(NumPHIWrites,
"Number of scalar phi writes after DeLICM");
74 "Number of scalar phi writes nested in affine loops after DeLICM");
75STATISTIC(NumSingletonWrites,
"Number of singleton writes after DeLICM");
77 "Number of singleton writes nested in affine loops after DeLICM");
103 bool InclOverwrite) {
109 auto Result = computeReachingOverwrite(
110 std::move(Schedule), std::move(WritesMap), InclPrevWrite, InclOverwrite);
112 return Result.domain_factor_range();
125 isl::set Writes,
bool InclPrevWrite,
126 bool InclOverwrite) {
133 isl::space ResultSpace = ScatterSpace.map_from_domain_and_range(DomSpace);
134 return singleton(std::move(ReachOverwrite), ResultSpace);
189class Knowledge final {
242 void checkConsistency()
const {
258 auto Universe = Occupied.
unite(Unused);
273 : Occupied(std::move(Occupied)), Unused(std::move(Unused)),
274 Known(std::move(Known)), Written(std::move(Written)) {
279 bool isUsable()
const {
285 void print(llvm::raw_ostream &OS,
unsigned Indent = 0)
const {
288 OS.indent(Indent) <<
"Occupied: " << Occupied <<
"\n";
290 OS.indent(Indent) <<
"Occupied: <Everything else not in Unused>\n";
292 OS.indent(Indent) <<
"Unused: " << Unused <<
"\n";
294 OS.indent(Indent) <<
"Unused: <Everything else not in Occupied>\n";
295 OS.indent(Indent) <<
"Known: " << Known <<
"\n";
296 OS.indent(Indent) <<
"Written : " << Written <<
'\n';
298 OS.indent(Indent) <<
"Invalid knowledge\n";
303 void learnFrom(Knowledge That) {
308 "This function is only prepared to learn occupied elements from That");
309 assert(Occupied.
is_null() &&
"This function does not implement "
311 "this->Occupied.unite(That.Occupied);`");
313 Unused = Unused.
subtract(That.Occupied);
314 Known = Known.
unite(That.Known);
315 Written = Written.
unite(That.Written);
339 const Knowledge &Proposed,
340 llvm::raw_ostream *OS =
nullptr,
341 unsigned Indent = 0) {
347 auto ExistingUniverse = Existing.Occupied.
unite(Existing.Unused);
348 auto ProposedUniverse = Proposed.Occupied.
unite(Proposed.Unused);
349 assert(ExistingUniverse.is_equal(ProposedUniverse) &&
350 "Both inputs' Knowledges must be over the same universe");
379 auto ProposedValues = Proposed.Known.
unite(ProposedOccupiedAnyVal);
382 auto ExistingValues = Existing.Known.
unite(ExistingUnusedAnyVal);
384 auto MatchingVals = ExistingValues.
intersect(ProposedValues);
385 auto Matches = MatchingVals.
domain();
390 if (!Proposed.Occupied.
is_subset(Matches)) {
392 auto Conflicting = Proposed.Occupied.
subtract(Matches);
393 auto ExistingConflictingKnown =
395 auto ProposedConflictingKnown =
398 OS->indent(Indent) <<
"Proposed lifetime conflicting with Existing's\n";
399 OS->indent(Indent) <<
"Conflicting occupied: " << Conflicting <<
"\n";
400 if (!ExistingConflictingKnown.is_empty())
402 <<
"Existing Known: " << ExistingConflictingKnown <<
"\n";
403 if (!ProposedConflictingKnown.is_empty())
405 <<
"Proposed Known: " << ProposedConflictingKnown <<
"\n";
429 auto ProposedFixedDefs =
431 auto ProposedFixedKnown =
434 auto ExistingConflictingWrites =
436 auto ExistingConflictingWritesDomain = ExistingConflictingWrites.
domain();
438 auto CommonWrittenVal =
439 ProposedFixedKnown.
intersect(ExistingConflictingWrites);
440 auto CommonWrittenValDomain = CommonWrittenVal.domain();
442 if (!ExistingConflictingWritesDomain.is_subset(CommonWrittenValDomain)) {
444 auto ExistingConflictingWritten =
445 ExistingConflictingWrites.subtract_domain(CommonWrittenValDomain);
446 auto ProposedConflictingKnown = ProposedFixedKnown.subtract_domain(
447 ExistingConflictingWritten.domain());
450 <<
"Proposed a lifetime where there is an Existing write into it\n";
451 OS->indent(Indent) <<
"Existing conflicting writes: "
452 << ExistingConflictingWritten <<
"\n";
453 if (!ProposedConflictingKnown.is_empty())
455 <<
"Proposed conflicting known: " << ProposedConflictingKnown
462 auto ExistingAvailableDefs =
464 auto ExistingKnownDefs =
467 auto ProposedWrittenDomain = Proposed.Written.
domain();
468 auto KnownIdentical = ExistingKnownDefs.
intersect(Proposed.Written);
469 auto IdenticalOrUnused =
470 ExistingAvailableDefs.
unite(KnownIdentical.domain());
471 if (!ProposedWrittenDomain.is_subset(IdenticalOrUnused)) {
473 auto Conflicting = ProposedWrittenDomain.subtract(IdenticalOrUnused);
474 auto ExistingConflictingKnown =
475 ExistingKnownDefs.intersect_domain(Conflicting);
476 auto ProposedConflictingWritten =
479 OS->indent(Indent) <<
"Proposed writes into range used by Existing\n";
480 OS->indent(Indent) <<
"Proposed conflicting writes: "
481 << ProposedConflictingWritten <<
"\n";
482 if (!ExistingConflictingKnown.is_empty())
484 <<
"Existing conflicting known: " << ExistingConflictingKnown
492 auto ExistingWrittenDomain = Existing.Written.
domain();
498 ExistingKnownWritten.intersect(ProposedKnownWritten).domain();
500 if (!BothWritten.is_subset(CommonWritten)) {
502 auto Conflicting = BothWritten.subtract(CommonWritten);
503 auto ExistingConflictingWritten =
505 auto ProposedConflictingWritten =
508 OS->indent(Indent) <<
"Proposed writes at the same time as an already "
510 OS->indent(Indent) <<
"Conflicting writes: " << Conflicting <<
"\n";
511 if (!ExistingConflictingWritten.is_empty())
513 <<
"Exiting write: " << ExistingConflictingWritten <<
"\n";
514 if (!ProposedConflictingWritten.is_empty())
516 <<
"Proposed write: " << ProposedConflictingWritten <<
"\n";
529 Knowledge OriginalZone;
536 int NumberOfCompatibleTargets = 0;
540 int NumberOfTargetsMapped = 0;
543 int NumberOfMappedValueScalars = 0;
546 int NumberOfMappedPHIScalars = 0;
559 raw_ostream *OS =
nullptr;
561 return Knowledge::isConflicting(Zone, Proposed, OS, 4);
570 auto *MA =
S->getValueDef(SAI);
574 <<
" Reject because value is read-only within the scop\n");
582 auto Inst = MA->getAccessInstruction();
583 for (
auto User : Inst->users()) {
584 if (!isa<Instruction>(User))
586 auto UserInst = cast<Instruction>(User);
588 if (!
S->contains(UserInst)) {
589 POLLY_DEBUG(dbgs() <<
" Reject because value is escaping\n");
598 auto *MA =
S->getPHIRead(SAI);
603 auto PHI = cast<PHINode>(MA->getAccessInstruction());
604 for (
auto Incoming :
PHI->blocks()) {
605 if (!
S->contains(Incoming)) {
607 <<
" Reject because at least one incoming block is "
608 "not in the scop region\n");
616 POLLY_DEBUG(dbgs() <<
" Reject ExitPHI or other non-value\n");
628 std::tuple<isl::union_map, isl::map>
633 auto Reads = makeEmptyUnionSet();
636 for (
auto *MA :
S->getValueUses(SAI))
637 Reads = Reads.unite(getDomainFor(MA));
640 auto ReadSchedule = getScatterFor(Reads);
642 auto *DefMA =
S->getValueDef(SAI);
646 auto Writes = getDomainFor(DefMA);
649 auto WriteScatter = getScatterFor(Writes);
652 auto ReachDef = getScalarReachingDefinition(DefMA->getStatement());
661 Writes.
get_space().map_from_domain_and_range(ScatterSpace));
664 auto Lifetime =
betweenScatter(WriteScatter, UseScatter,
false,
true);
667 auto DefUses = Uses.domain_factor_domain();
669 return std::make_pair(DefUses, Lifetime);
682 auto *DefMA =
S->getValueDef(SAI);
683 assert(DefMA->isValueKind());
684 assert(DefMA->isMustWrite());
685 auto *V = DefMA->getAccessValue();
686 auto *DefInst = DefMA->getAccessInstruction();
689 if (!DefMA->getLatestScopArrayInfo()->isValueKind())
693 auto DefSched = getScatterFor(DefMA);
697 auto DefTarget = TargetElt.
apply_domain(DefSched.reverse());
699 POLLY_DEBUG(dbgs() <<
" Def Mapping: " << DefTarget <<
'\n');
701 auto OrigDomain = getDomainFor(DefMA);
702 auto MappedDomain = DefTarget.domain();
703 if (!OrigDomain.is_subset(MappedDomain)) {
706 <<
" Reject because mapping does not encompass all instances\n");
716 std::tie(DefUses, Lifetime) = computeValueUses(SAI);
717 POLLY_DEBUG(dbgs() <<
" Lifetime: " << Lifetime <<
'\n');
727 if (DelicmComputeKnown)
728 ValInst = makeValInst(V, DefMA->getStatement(),
729 LI->getLoopFor(DefInst->getParent()));
734 auto EltKnownTranslator = DefTarget.range_product(Lifetime);
737 auto EltKnown = ValInst.
apply_domain(EltKnownTranslator);
741 auto WrittenTranslator = DefTarget.range_product(DefSched);
744 auto DefEltSched = ValInst.
apply_domain(WrittenTranslator);
754 mapValue(SAI, std::move(DefTarget), std::move(UseTarget),
755 std::move(Lifetime), std::move(Proposed));
760 void applyLifetime(Knowledge Proposed) {
761 Zone.learnFrom(std::move(Proposed));
780 Knowledge Proposed) {
782 for (
auto *MA :
S->getValueUses(SAI)) {
784 auto Domain = getDomainFor(MA);
794 auto *WA =
S->getValueDef(SAI);
795 WA->setNewAccessRelation(DefTarget);
796 applyLifetime(Proposed);
798 MappedValueScalars++;
799 NumberOfMappedValueScalars += 1;
803 bool IsCertain =
true) {
806 if (!DelicmComputeKnown)
818 auto Result = makeEmptyUnionMap();
821 for (
auto *MA :
S->getPHIIncomings(SAI)) {
824 auto *WriteStmt = MA->getStatement();
826 auto Incoming = MA->getIncoming();
827 assert(!Incoming.empty());
828 if (Incoming.size() == 1) {
829 ValInst = makeValInst(Incoming[0].second, WriteStmt,
830 LI->getLoopFor(Incoming[0].first));
840 Result = Result.unite(ValInst);
843 assert(Result.is_single_valued() &&
844 "Cannot have multiple incoming values for same incoming statement");
857 auto *PHIRead =
S->getPHIRead(SAI);
858 assert(PHIRead->isPHIKind());
859 assert(PHIRead->isRead());
862 if (!PHIRead->getLatestScopArrayInfo()->isPHIKind())
866 auto PHISched = getScatterFor(PHIRead);
869 auto PHITarget = PHISched.apply_range(TargetElt);
871 POLLY_DEBUG(dbgs() <<
" Mapping: " << PHITarget <<
'\n');
873 auto OrigDomain = getDomainFor(PHIRead);
874 auto MappedDomain = PHITarget.domain();
875 if (!OrigDomain.is_subset(MappedDomain)) {
878 <<
" Reject because mapping does not encompass all instances\n");
883 auto PerPHIWrites = computePerPHI(SAI);
884 if (PerPHIWrites.is_null()) {
886 dbgs() <<
" Reject because cannot determine incoming values\n");
891 auto WritesTarget = PerPHIWrites.apply_domain(PHITarget).reverse();
897 for (
auto *MA :
S->getPHIIncomings(SAI))
898 UniverseWritesDom = UniverseWritesDom.unite(getDomainFor(MA));
900 auto RelevantWritesTarget = WritesTarget;
901 if (DelicmOverapproximateWrites)
902 WritesTarget = expandMapping(WritesTarget, UniverseWritesDom);
904 auto ExpandedWritesDom = WritesTarget.domain();
905 if (!DelicmPartialWrites &&
906 !UniverseWritesDom.is_subset(ExpandedWritesDom)) {
908 dbgs() <<
" Reject because did not find PHI write mapping for "
910 if (DelicmOverapproximateWrites)
912 << RelevantWritesTarget <<
'\n');
913 POLLY_DEBUG(dbgs() <<
" Deduced Mapping: " << WritesTarget
916 << UniverseWritesDom.subtract(ExpandedWritesDom)
927 auto Lifetime =
betweenScatter(PerPHIWriteScatter, PHISched,
false,
true);
929 POLLY_DEBUG(dbgs() <<
" Lifetime: " << Lifetime <<
"\n");
935 auto WrittenValue = determinePHIWrittenValues(SAI);
938 auto WrittenTranslator = WritesTarget.range_product(Schedule);
941 auto Written = WrittenValue.apply_domain(WrittenTranslator);
945 auto LifetimeTranslator = WritesTarget.range_product(WriteLifetime);
951 auto EltLifetimeInst = WrittenKnownValue.apply_domain(LifetimeTranslator);
955 auto Occupied = LifetimeTranslator.range();
958 Knowledge Proposed(Occupied, {}, EltLifetimeInst, Written);
962 mapPHI(SAI, std::move(PHITarget), std::move(WritesTarget),
963 std::move(Lifetime), std::move(Proposed));
983 Knowledge Proposed) {
988 for (
auto *MA :
S->getPHIIncomings(SAI)) {
990 auto Domain = getDomainFor(MA);
997 Domain.get_space().map_from_domain_and_range(ElementSpace);
999 MA->setNewAccessRelation(NewAccRelMap);
1003 auto *PHIRead =
S->getPHIRead(SAI);
1004 PHIRead->setNewAccessRelation(ReadTarget);
1005 applyLifetime(Proposed);
1008 NumberOfMappedPHIScalars++;
1021 bool collapseScalarsToStore(
MemoryAccess *TargetStoreMA) {
1028 auto TargetDom = getDomainFor(TargetStmt);
1031 auto TargetAccRel = getAccessRelationFor(TargetStoreMA);
1040 Target = computeScalarReachingOverwrite(Schedule, TargetDom,
false,
true);
1046 "The only reason that these things have not been computed should "
1047 "be if the max-operations limit hit");
1049 dbgs() <<
"collapseScalarsToStore exceeded max_operations\n");
1050 DebugLoc Begin, End;
1052 OptimizationRemarkAnalysis R(
DEBUG_TYPE,
"OutOfQuota", Begin,
1054 R <<
"maximal number of operations exceeded during "
1055 "collapseScalarsToStore";
1056 S->getFunction().getContext().diagnose(R);
1066 auto EltTarget = Target.
apply_range(TargetAccRel);
1068 POLLY_DEBUG(dbgs() <<
" Target mapping is " << EltTarget <<
'\n');
1071 SmallVector<MemoryAccess *, 16> Worklist;
1074 SmallPtrSet<const ScopArrayInfo *, 16> Closed;
1077 auto ProcessAllIncoming = [&](
ScopStmt *Stmt) {
1078 for (
auto *MA : *Stmt) {
1079 if (!MA->isLatestScalarKind())
1084 Worklist.push_back(MA);
1089 if (
auto *WrittenValInputMA = TargetStmt->lookupInputAccessOf(WrittenVal))
1090 Worklist.push_back(WrittenValInputMA);
1092 ProcessAllIncoming(TargetStmt);
1094 auto AnyMapped =
false;
1095 auto &DL =
S->getRegion().getEntry()->getModule()->getDataLayout();
1099 while (!Worklist.empty()) {
1100 auto *MA = Worklist.pop_back_val();
1102 auto *SAI = MA->getScopArrayInfo();
1103 if (Closed.count(SAI))
1106 POLLY_DEBUG(dbgs() <<
"\n Trying to map " << MA <<
" (SAI: " << SAI
1110 if (!isMappable(SAI))
1113 auto MASize = DL.getTypeAllocSize(MA->getAccessValue()->getType());
1114 if (MASize > StoreSize) {
1116 dbgs() <<
" Reject because storage size is insufficient\n");
1122 if (!tryMapValue(SAI, EltTarget))
1125 auto *DefAcc =
S->getValueDef(SAI);
1126 ProcessAllIncoming(DefAcc->getStatement());
1134 if (!tryMapPHI(SAI, EltTarget))
1138 for (
auto *PHIWrite :
S->getPHIIncomings(SAI)) {
1139 auto *PHIWriteStmt = PHIWrite->getStatement();
1140 bool FoundAny =
false;
1141 for (
auto Incoming : PHIWrite->getIncoming()) {
1142 auto *IncomingInputMA =
1143 PHIWriteStmt->lookupInputAccessOf(Incoming.second);
1144 if (!IncomingInputMA)
1147 Worklist.push_back(IncomingInputMA);
1152 ProcessAllIncoming(PHIWrite->getStatement());
1162 NumberOfTargetsMapped++;
1173 false,
false,
true);
1175 auto Result = ArrayUnused.wrap();
1203 auto Map = getAccessRelationFor(MA);
1204 auto Set = Map.range();
1205 return Set.is_singleton();
1209 void printStatistics(llvm::raw_ostream &OS,
int Indent = 0)
const {
1210 OS.indent(Indent) <<
"Statistics {\n";
1211 OS.indent(Indent + 4) <<
"Compatible overwrites: "
1212 << NumberOfCompatibleTargets <<
"\n";
1213 OS.indent(Indent + 4) <<
"Overwrites mapped to: " << NumberOfTargetsMapped
1215 OS.indent(Indent + 4) <<
"Value scalars mapped: "
1216 << NumberOfMappedValueScalars <<
'\n';
1217 OS.indent(Indent + 4) <<
"PHI scalars mapped: "
1218 << NumberOfMappedPHIScalars <<
'\n';
1219 OS.indent(Indent) <<
"}\n";
1223 DeLICMImpl(
Scop *
S, LoopInfo *LI)
1225 MaxOpGuard(IslCtx.get(), DelicmMaxOps,
false) {}
1230 bool computeZone() {
1232 collectCompatibleElts();
1242 EltUnused = computeLifetime();
1243 EltKnown = computeKnown(
true,
false);
1244 EltWritten = computeWritten();
1250 "The only reason that these things have not been computed should "
1251 "be if the max-operations limit hit");
1253 POLLY_DEBUG(dbgs() <<
"DeLICM analysis exceeded max_operations\n");
1254 DebugLoc Begin, End;
1256 OptimizationRemarkAnalysis R(
DEBUG_TYPE,
"OutOfQuota", Begin,
1258 R <<
"maximal number of operations exceeded during zone analysis";
1259 S->getFunction().getContext().diagnose(R);
1263 Zone = OriginalZone = Knowledge({}, EltUnused, EltKnown, EltWritten);
1264 POLLY_DEBUG(dbgs() <<
"Computed Zone:\n"; OriginalZone.print(dbgs(), 4));
1266 assert(Zone.isUsable() && OriginalZone.isUsable());
1275 void greedyCollapse() {
1276 bool Modified =
false;
1277 bool MaxOpQuotaExceeded =
false;
1279 for (
auto &Stmt : *
S) {
1280 for (
auto *MA : Stmt) {
1288 <<
" pruned because it is a MAY_WRITE\n");
1289 OptimizationRemarkMissed R(
DEBUG_TYPE,
"TargetMayWrite",
1291 R <<
"Skipped possible mapping target because it is not an "
1292 "unconditional overwrite";
1293 S->getFunction().getContext().diagnose(R);
1297 if (Stmt.getNumIterators() == 0) {
1299 <<
" pruned because it is not in a loop\n");
1300 OptimizationRemarkMissed R(
DEBUG_TYPE,
"WriteNotInLoop",
1302 R <<
"skipped possible mapping target because it is not in a loop";
1303 S->getFunction().getContext().diagnose(R);
1307 if (isScalarAccess(MA)) {
1310 <<
" pruned because it writes only a single element\n");
1311 OptimizationRemarkMissed R(
DEBUG_TYPE,
"ScalarWrite",
1313 R <<
"skipped possible mapping target because the memory location "
1314 "written to does not depend on its outer loop";
1315 S->getFunction().getContext().diagnose(R);
1321 <<
" pruned because it is not a StoreInst\n");
1322 OptimizationRemarkMissed R(
DEBUG_TYPE,
"NotAStore",
1324 R <<
"skipped possible mapping target because non-store instructions "
1325 "are not supported";
1326 S->getFunction().getContext().diagnose(R);
1344 <<
" is incompatible because it writes multiple "
1345 "elements per instance\n");
1346 OptimizationRemarkMissed R(
DEBUG_TYPE,
"NonFunctionalAccRel",
1348 R <<
"skipped possible mapping target because it writes more than "
1350 S->getFunction().getContext().diagnose(R);
1355 if (!TouchedElts.
is_subset(CompatibleElts)) {
1359 <<
" is incompatible because it touches incompatible elements\n");
1360 OptimizationRemarkMissed R(
DEBUG_TYPE,
"IncompatibleElts",
1362 R <<
"skipped possible mapping target because a target location "
1363 "cannot be reliably analyzed";
1364 S->getFunction().getContext().diagnose(R);
1368 assert(isCompatibleAccess(MA));
1369 NumberOfCompatibleTargets++;
1370 POLLY_DEBUG(dbgs() <<
"Analyzing target access " << MA <<
"\n");
1371 if (collapseScalarsToStore(MA))
1374 MaxOpQuotaExceeded =
true;
1378 if (MaxOpQuotaExceeded)
1383 DeLICMScopsModified++;
1387 void print(llvm::raw_ostream &OS,
int Indent = 0) {
1388 if (!Zone.isUsable()) {
1389 OS.indent(Indent) <<
"Zone not computed\n";
1393 printStatistics(OS, Indent);
1394 if (!isModified()) {
1395 OS.indent(Indent) <<
"No modification has been made\n";
1398 printAccesses(OS, Indent);
1402 bool isModified()
const {
1403 return NumberOfTargetsMapped > 0 || NumberOfMappedValueScalars > 0 ||
1404 NumberOfMappedPHIScalars > 0;
1408static std::unique_ptr<DeLICMImpl> collapseToUnused(
Scop &
S, LoopInfo &LI) {
1409 std::unique_ptr<DeLICMImpl> Impl = std::make_unique<DeLICMImpl>(&
S, &LI);
1411 if (!Impl->computeZone()) {
1412 POLLY_DEBUG(dbgs() <<
"Abort because cannot reliably compute lifetimes\n");
1416 POLLY_DEBUG(dbgs() <<
"Collapsing scalars to unused array elements...\n");
1417 Impl->greedyCollapse();
1425static std::unique_ptr<DeLICMImpl> runDeLICMImpl(
Scop &
S, LoopInfo &LI) {
1426 std::unique_ptr<DeLICMImpl> Impl = collapseToUnused(
S, LI);
1445 llvm::raw_ostream *OS,
unsigned Indent) {
1446 Knowledge Existing(std::move(ExistingOccupied), std::move(ExistingUnused),
1447 std::move(ExistingKnown), std::move(ExistingWrites));
1448 Knowledge Proposed(std::move(ProposedOccupied), std::move(ProposedUnused),
1449 std::move(ProposedKnown), std::move(ProposedWrites));
1451 return Knowledge::isConflicting(Existing, Proposed, OS, Indent);
1455 LoopInfo &LI = *
S.getLI();
1456 std::unique_ptr<DeLICMImpl> Impl = runDeLICMImpl(
S, LI);
1458 if (PollyPrintDeLICM) {
1459 outs() <<
"Printing analysis 'Polly - DeLICM/DePRE' for region: '"
1460 <<
S.getName() <<
"' in function '" <<
S.getFunction().getName()
1463 assert(Impl->getScop() == &
S);
1465 outs() <<
"DeLICM result:\n";
1466 Impl->print(outs());
1470 return Impl->isModified();
llvm::cl::OptionCategory PollyCategory
STATISTIC(ScopFound, "Number of valid Scops")
isl::checked::set wrap() 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::space range() const
isl::checked::union_set range() const
isl::checked::union_map reverse() const
isl::checked::union_map unite(isl::checked::union_map umap2) const
isl::checked::union_set domain() const
isl::checked::union_map apply_range(isl::checked::union_map umap2) const
isl::checked::space get_space() const
isl::checked::union_map apply_domain(isl::checked::union_map umap2) const
isl::checked::union_map intersect_domain(isl::checked::space space) const
isl::checked::union_map coalesce() const
isl::checked::union_map gist_domain(isl::checked::union_set uset) const
boolean is_single_valued() const
isl::checked::union_map intersect(isl::checked::union_map umap2) const
isl::checked::union_set subtract(isl::checked::union_set uset2) const
boolean is_disjoint(const isl::checked::union_set &uset2) const
boolean is_subset(const isl::checked::union_set &uset2) const
isl::checked::union_set unite(isl::checked::union_set uset2) const
isl::checked::union_set intersect(isl::checked::union_set uset2) const
static isl::map from_union_map(isl::union_map umap)
static isl::union_map from_domain(isl::union_set uset)
static isl::union_set empty(isl::ctx ctx)
Scoped limit of ISL operations.
bool hasQuotaExceeded() const
Return whether the current quota has exceeded.
IslQuotaScope enter(bool AllowReturnNull=true)
Enter a scope that can handle out-of-quota errors.
Scope guard for code that allows arbitrary isl function to return an error if the max-operations quot...
bool hasQuotaExceeded() const
Return whether the current quota has exceeded.
Represent memory accesses in statements.
isl::map getLatestAccessRelation() const
Return the newest access relation of this access.
bool isLatestArrayKind() const
Whether storage memory is either an custom .s2a/.phiops alloca (false) or an existing pointer into an...
bool isWrite() const
Is this a write memory access?
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
bool isMustWrite() const
Is this a must-write memory access?
ScopStmt * getStatement() const
Get the statement that contains this memory access.
bool isMayWrite() const
Is this a may-write memory access?
Value * getAccessValue() const
Return the access value of this memory access.
A class to store information about arrays in the SCoP.
bool isValueKind() const
Is this array info modeling an llvm::Value?
bool isPHIKind() const
Is this array info modeling special PHI node memory?
Base class for algorithms based on zones, like DeLICM.
isl::map makeValInst(llvm::Value *Val, ScopStmt *UserStmt, llvm::Loop *Scope, bool IsCertain=true)
Create a mapping from a statement instance to the instance of an llvm::Value that can be used in ther...
enum isl_error isl_ctx_last_error(isl_ctx *ctx)
isl::map betweenScatter(isl::map From, isl::map To, bool InclFrom, bool InclTo)
Construct a range of timepoints between two timepoints.
isl::union_map makeUnknownForDomain(isl::union_set Domain)
Create a domain-to-unknown value mapping.
isl::union_map computeReachingWrite(isl::union_map Schedule, isl::union_map Writes, bool Reverse, bool InclPrevDef, bool InclNextDef)
Compute the reaching definition statement or the next overwrite for each definition of an array eleme...
isl::union_map computeArrayUnused(isl::union_map Schedule, isl::union_map Writes, isl::union_map Reads, bool ReadEltInSameInst, bool InclLastRead, bool InclWrite)
Compute the timepoints where the contents of an array element are not used.
void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End)
Set the begin and end source location for the region limited by P.
@ Value
MemoryKind::Value: Models an llvm::Value.
@ PHI
MemoryKind::PHI: Models PHI nodes within the SCoP.
bool isConflicting(isl::union_set ExistingOccupied, isl::union_set ExistingUnused, isl::union_map ExistingKnown, isl::union_map ExistingWrites, isl::union_set ProposedOccupied, isl::union_set ProposedUnused, isl::union_map ProposedKnown, isl::union_map ProposedWrites, llvm::raw_ostream *OS=nullptr, unsigned Indent=0)
Determine whether two lifetimes are conflicting.
void simplify(isl::set &Set)
Simplify a set inplace.
BBPair getBBPairForRegion(const Region *R)
Return the region delimiters (entry & exit block) of R.
isl::union_map applyDomainRange(isl::union_map UMap, isl::union_map Func)
Apply a map to the 'middle' of another relation.
isl::union_set convertZoneToTimepoints(isl::union_set Zone, bool InclStart, bool InclEnd)
Convert a zone (range between timepoints) to timepoints.
isl::map singleton(isl::union_map UMap, isl::space ExpectedSpace)
If by construction a union map is known to contain only a single map, return it.
isl::union_map filterKnownValInst(const isl::union_map &UMap)
Return only the mappings that map to known values.
isl::space getScatterSpace(const isl::union_map &Schedule)
Return the scatter space of a Schedule.
int NumValueWritesInLoops
int NumSingletonWritesInLoops
static TupleKindPtr Domain("Domain")
isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap)