Skip to content

Commit

Permalink
[ForwardOpTree] Use known array content analysis to forward load inst…
Browse files Browse the repository at this point in the history
…ructions.

This is an addition to the -polly-optree pass that reuses the array
content analysis from DeLICM to find array elements that contain the
same value as the value loaded when the target statement instance
is executed.

The analysis is now enabled by default.

The known content analysis could also be used to rematerialize any
llvm::Value that was written to some array element, but currently
only loads are forwarded.

Differential Revision: https://reviews.llvm.org/D36380

llvm-svn: 310279
  • Loading branch information
Meinersbur committed Aug 7, 2017
1 parent 4504fe2 commit 70af4f5
Show file tree
Hide file tree
Showing 15 changed files with 1,124 additions and 58 deletions.
6 changes: 5 additions & 1 deletion polly/include/polly/ScopInfo.h
Expand Up @@ -1528,7 +1528,11 @@ class ScopStmt {
}

/// Add @p Access to this statement's list of accesses.
void addAccess(MemoryAccess *Access);
///
/// @param Access The access to add.
/// @param Prepend If true, will add @p Access before all other instructions
/// (instead of appending it).
void addAccess(MemoryAccess *Access, bool Preprend = false);

/// Remove a MemoryAccess from this statement.
///
Expand Down
5 changes: 5 additions & 0 deletions polly/include/polly/Support/ISLTools.h
Expand Up @@ -368,6 +368,11 @@ isl::union_set convertZoneToTimepoints(isl::union_set Zone, bool InclStart,
isl::union_map convertZoneToTimepoints(isl::union_map Zone, isl::dim Dim,
bool InclStart, bool InclEnd);

/// Overload of convertZoneToTimepoints(isl::map,InclStart,InclEnd) to process
/// only a single map.
isl::map convertZoneToTimepoints(isl::map Zone, isl::dim Dim, bool InclStart,
bool InclEnd);

/// Distribute the domain to the tuples of a wrapped range map.
///
/// @param Map { Domain[] -> [Range1[] -> Range2[]] }
Expand Down
29 changes: 29 additions & 0 deletions polly/include/polly/ZoneAlgo.h
Expand Up @@ -67,6 +67,10 @@ class ZoneAlgorithm {
/// { DomainRead[] -> Element[] }
isl::union_map AllReads;

/// The loaded values (llvm::LoadInst) of all reads.
/// { [Element[] -> DomainRead[]] -> ValInst[] }
isl::union_map AllReadValInst;

/// Combined access relations of all MemoryKind::Array, MAY_WRITE accesses.
/// { DomainMayWrite[] -> Element[] }
isl::union_map AllMayWrites;
Expand All @@ -75,6 +79,11 @@ class ZoneAlgorithm {
/// { DomainMustWrite[] -> Element[] }
isl::union_map AllMustWrites;

/// Combined access relations of all MK_Array write accesses (union of
/// AllMayWrites and AllMustWrites).
/// { DomainWrite[] -> Element[] }
isl::union_map AllWrites;

/// The value instances written to array elements of all write accesses.
/// { [Element[] -> DomainWrite[]] -> ValInst[] }
isl::union_map AllWriteValInst;
Expand Down Expand Up @@ -220,6 +229,26 @@ class ZoneAlgorithm {
public:
/// Return the SCoP this object is analyzing.
Scop *getScop() const { return S; }

/// A reaching definition zone is known to have the definition's written value
/// if the definition is a MUST_WRITE.
///
/// @return { [Element[] -> Zone[]] -> ValInst[] }
isl::union_map computeKnownFromMustWrites() const;

/// A reaching definition zone is known to be the same value as any load that
/// reads from that array element in that period.
///
/// @return { [Element[] -> Zone[]] -> ValInst[] }
isl::union_map computeKnownFromLoad() const;

/// Compute which value an array element stores at every instant.
///
/// @param FromWrite Use stores as source of information.
/// @param FromRead Use loads as source of information.
///
/// @return { [Element[] -> Zone[]] -> ValInst[] }
isl::union_map computeKnown(bool FromWrite, bool FromRead) const;
};

/// Create a domain-to-unknown value mapping.
Expand Down
6 changes: 5 additions & 1 deletion polly/lib/Analysis/ScopInfo.cpp
Expand Up @@ -1276,7 +1276,7 @@ void ScopStmt::buildAccessRelations() {
}
}

void ScopStmt::addAccess(MemoryAccess *Access) {
void ScopStmt::addAccess(MemoryAccess *Access, bool Prepend) {
Instruction *AccessInst = Access->getAccessInstruction();

if (Access->isArrayKind()) {
Expand Down Expand Up @@ -1305,6 +1305,10 @@ void ScopStmt::addAccess(MemoryAccess *Access) {
PHIReads[PHI] = Access;
}

if (Prepend) {
MemAccs.insert(MemAccs.begin(), Access);
return;
}
MemAccs.push_back(Access);
}

Expand Down
15 changes: 15 additions & 0 deletions polly/lib/Support/ISLTools.cpp
Expand Up @@ -431,6 +431,21 @@ isl::union_map polly::convertZoneToTimepoints(isl::union_map Zone, isl::dim Dim,
return give(isl_union_map_union(Zone.take(), ShiftedZone.take()));
}

isl::map polly::convertZoneToTimepoints(isl::map Zone, isl::dim Dim,
bool InclStart, bool InclEnd) {
if (!InclStart && InclEnd)
return Zone;

auto ShiftedZone = shiftDim(Zone, Dim, -1, -1);
if (InclStart && !InclEnd)
return ShiftedZone;
else if (!InclStart && !InclEnd)
return give(isl_map_intersect(Zone.take(), ShiftedZone.take()));

assert(InclStart && InclEnd);
return give(isl_map_union(Zone.take(), ShiftedZone.take()));
}

isl::map polly::distributeDomain(isl::map Map) {
// Note that we cannot take Map apart into { Domain[] -> Range1[] } and {
// Domain[] -> Range2[] } and combine again. We would loose any relation
Expand Down
27 changes: 9 additions & 18 deletions polly/lib/Transform/DeLICM.cpp
Expand Up @@ -778,9 +778,15 @@ class DeLICMImpl : public ZoneAlgorithm {
isl_map_wrap(isl_map_apply_domain(Lifetime.copy(), DefTarget.copy())));
simplify(EltZone);

// When known knowledge is disabled, just return the unknown value. It will
// either get filtered out or conflict with itself.
// { DomainDef[] -> ValInst[] }
auto ValInst = makeValInst(V, DefMA->getStatement(),
LI->getLoopFor(DefInst->getParent()));
isl::map ValInst;
if (DelicmComputeKnown)
ValInst = makeValInst(V, DefMA->getStatement(),
LI->getLoopFor(DefInst->getParent()));
else
ValInst = makeUnknownForDomain(DefMA->getStatement());

// { DomainDef[] -> [Element[] -> Zone[]] }
auto EltKnownTranslator =
Expand Down Expand Up @@ -1209,21 +1215,6 @@ class DeLICMImpl : public ZoneAlgorithm {
return Result;
}

/// Compute which value an array element stores at every instant.
///
/// @return { [Element[] -> Zone[]] -> ValInst[] }
isl::union_map computeKnown() const {
// { [Element[] -> Zone[]] -> [Element[] -> DomainWrite[]] }
auto EltReachdDef =
distributeDomain(give(isl_union_map_curry(WriteReachDefZone.copy())));

// { [Element[] -> DomainWrite[]] -> ValInst[] }
auto AllKnownWriteValInst = filterKnownValInst(AllWriteValInst);

// { [Element[] -> Zone[]] -> ValInst[] }
return EltReachdDef.apply_range(AllKnownWriteValInst);
}

/// Determine when an array element is written to, and which value instance is
/// written.
///
Expand Down Expand Up @@ -1290,7 +1281,7 @@ class DeLICMImpl : public ZoneAlgorithm {
computeCommon();

EltUnused = computeLifetime();
EltKnown = computeKnown();
EltKnown = computeKnown(true, false);
EltWritten = computeWritten();
}
DeLICMAnalyzed++;
Expand Down

0 comments on commit 70af4f5

Please sign in to comment.