[polly] r334134 - [OpTree] Introduce shortcut for computing the def->target mapping. NFCI.
Michael Kruse via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 6 14:37:35 PDT 2018
Author: meinersbur
Date: Wed Jun 6 14:37:35 2018
New Revision: 334134
URL: http://llvm.org/viewvc/llvm-project?rev=334134&view=rev
Log:
[OpTree] Introduce shortcut for computing the def->target mapping. NFCI.
In case the schedule has not changed and the operand tree root uses a
value defined in an ancestor loop, the def-to-target mapping is trivial.
For instance, the SCoP
for (int i < 0; i < N; i+=1) {
DefStmt:
D = ...;
for (int j < 0; j < N; j+=1) {
TargetStmt:
use(D);
}
}
has DefStmt-to-TargetStmt mapping of
{ DefStmt[i] -> TargetStmt[i,j] }
This should apply on the majority of def-to-target mappings.
This patch detects this case and directly constructs the expected
mapping. It assumes that the mapping never crosses the loop header
DefStmt is in, which ForwardOpTree does not support at the moment
anyway.
Differential Revision: https://reviews.llvm.org/D47752
Modified:
polly/trunk/include/polly/ScopInfo.h
polly/trunk/lib/Analysis/ScopInfo.cpp
polly/trunk/lib/Transform/ForwardOpTree.cpp
Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=334134&r1=334133&r2=334134&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Wed Jun 6 14:37:35 2018
@@ -1888,6 +1888,10 @@ private:
/// in a schedule tree is given in the isl manual.
isl::schedule Schedule = nullptr;
+ /// Whether the schedule has been modified after derived from the CFG by
+ /// ScopBuilder.
+ bool ScheduleModified = false;
+
/// The set of minimal/maximal accesses for each alias group.
///
/// When building runtime alias checks we look at all memory instructions and
@@ -2997,6 +3001,10 @@ public:
/// NewSchedule The new schedule (given as schedule tree).
void setScheduleTree(isl::schedule NewSchedule);
+ /// Whether the schedule is the original schedule as derived from the CFG by
+ /// ScopBuilder.
+ bool isOriginalSchedule() const { return !ScheduleModified; }
+
/// Intersects the domains of all statements in the SCoP.
///
/// @return true if a change was made
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=334134&r1=334133&r2=334134&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Wed Jun 6 14:37:35 2018
@@ -4521,10 +4521,12 @@ void Scop::setSchedule(isl::union_map Ne
auto S = isl::schedule::from_domain(getDomains());
Schedule = S.insert_partial_schedule(
isl::multi_union_pw_aff::from_union_map(NewSchedule));
+ ScheduleModified = true;
}
void Scop::setScheduleTree(isl::schedule NewSchedule) {
Schedule = NewSchedule;
+ ScheduleModified = true;
}
bool Scop::restrictDomains(isl::union_set Domain) {
Modified: polly/trunk/lib/Transform/ForwardOpTree.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Transform/ForwardOpTree.cpp?rev=334134&r1=334133&r2=334134&view=diff
==============================================================================
--- polly/trunk/lib/Transform/ForwardOpTree.cpp (original)
+++ polly/trunk/lib/Transform/ForwardOpTree.cpp Wed Jun 6 14:37:35 2018
@@ -396,6 +396,14 @@ public:
return UseScatter.apply_range(ReachDefTimepoints);
}
+ /// Is @p InnerLoop nested inside @p OuterLoop?
+ static bool isInsideLoop(Loop *OuterLoop, Loop *InnerLoop) {
+ // If OuterLoop is nullptr, we cannot call its contains() method. In this
+ // case OuterLoop represents the 'top level' and therefore contains all
+ // loop.
+ return !OuterLoop || OuterLoop->contains(InnerLoop);
+ }
+
/// Get a domain translation map from a (scalar) definition to the statement
/// where the definition is being moved to.
///
@@ -422,6 +430,43 @@ public:
getDomainFor(TargetStmt).get_space().map_from_set());
isl::map &Result = DefToTargetCache[std::make_pair(TargetStmt, DefStmt)];
+
+ // This is a shortcut in case the schedule is still the original and
+ // TargetStmt is in the same or nested inside DefStmt's loop. With the
+ // additional assumption that operand trees do not cross DefStmt's loop
+ // header, then TargetStmt's instance shared coordinated are the same as
+ // DefStmt's coordinated. All TargetStmt instances with this prefix share
+ // the same DefStmt instance.
+ // Model:
+ //
+ // for (int i < 0; i < N; i+=1) {
+ // DefStmt:
+ // D = ...;
+ // for (int j < 0; j < N; j+=1) {
+ // TargetStmt:
+ // use(D);
+ // }
+ // }
+ //
+ // Here, the value used in TargetStmt is defined in the corresponding
+ // DefStmt, i.e.
+ //
+ // { DefStmt[i] -> TargetStmt[i,j] }
+ //
+ // In practice, this should cover the majority of cases.
+ if (S->isOriginalSchedule() &&
+ isInsideLoop(DefStmt->getSurroundingLoop(),
+ TargetStmt->getSurroundingLoop())) {
+ isl::set DefDomain = getDomainFor(DefStmt);
+ isl::set TargetDomain = getDomainFor(TargetStmt);
+ assert(DefDomain.dim(isl::dim::set) <= TargetDomain.dim(isl::dim::set));
+
+ Result = isl::map::from_domain_and_range(DefDomain, TargetDomain);
+ for (unsigned i = 0, DefDims = DefDomain.dim(isl::dim::set); i < DefDims;
+ i += 1)
+ Result = Result.equate(isl::dim::in, i, isl::dim::out, i);
+ }
+
if (!Result) {
// { DomainDef[] -> DomainTarget[] }
Result = computeUseToDefFlowDependency(TargetStmt, DefStmt).reverse();
More information about the llvm-commits
mailing list