forked from OSchip/llvm-project
[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 llvm-svn: 334134
This commit is contained in:
parent
6fda6b1210
commit
2dab88e652
|
@ -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
|
||||
|
|
|
@ -4521,10 +4521,12 @@ void Scop::setSchedule(isl::union_map NewSchedule) {
|
|||
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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue