mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 15:41:35 +08:00
[ZoneAlgo] Use getDefToTarget in makeValInst. NFC.
Move the optimized getDefToTarget() from ForwardOpTree to ZoneAlgo such that it can be used by makeValInst. This reduces the compile time of GrTestUtils of the aosp buildbot from 2m46s to 21s, which should fix the timeout issue. Differential Revision: https://reviews.llvm.org/D48579 llvm-svn: 335606
This commit is contained in:
@@ -181,9 +181,6 @@ private:
|
||||
/// original load. { ValInst[] -> ValInst[] }
|
||||
isl::union_map Translator;
|
||||
|
||||
/// A cache for getDefToTarget().
|
||||
DenseMap<std::pair<ScopStmt *, ScopStmt *>, isl::map> DefToTargetCache;
|
||||
|
||||
/// Get list of array elements that do contain the same ValInst[] at Domain[].
|
||||
///
|
||||
/// @param ValInst { Domain[] -> ValInst[] }
|
||||
@@ -374,108 +371,6 @@ public:
|
||||
return Access;
|
||||
}
|
||||
|
||||
/// For an llvm::Value defined in @p DefStmt, compute the RAW dependency for a
|
||||
/// use in every instance of @p UseStmt.
|
||||
///
|
||||
/// @param UseStmt Statement a scalar is used in.
|
||||
/// @param DefStmt Statement a scalar is defined in.
|
||||
///
|
||||
/// @return { DomainUse[] -> DomainDef[] }
|
||||
isl::map computeUseToDefFlowDependency(ScopStmt *UseStmt, ScopStmt *DefStmt) {
|
||||
// { DomainUse[] -> Scatter[] }
|
||||
isl::map UseScatter = getScatterFor(UseStmt);
|
||||
|
||||
// { Zone[] -> DomainDef[] }
|
||||
isl::map ReachDefZone = getScalarReachingDefinition(DefStmt);
|
||||
|
||||
// { Scatter[] -> DomainDef[] }
|
||||
isl::map ReachDefTimepoints =
|
||||
convertZoneToTimepoints(ReachDefZone, isl::dim::in, false, true);
|
||||
|
||||
// { DomainUse[] -> DomainDef[] }
|
||||
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.
|
||||
///
|
||||
/// @p TargetStmt can also be seen an llvm::Use of an llvm::Value in
|
||||
/// @p DefStmt. In addition, we allow transitive uses:
|
||||
///
|
||||
/// DefStmt -> MiddleStmt -> TargetStmt
|
||||
///
|
||||
/// where an operand tree of instructions in DefStmt and MiddleStmt are to be
|
||||
/// moved to TargetStmt. To be generally correct, we also need to know all the
|
||||
/// intermediate statements. However, we make use of the fact that we
|
||||
/// currently do not support a move from a loop body across its header such
|
||||
/// that only the first definition and the target statement are relevant.
|
||||
///
|
||||
/// @param DefStmt Statement from where a definition might be moved from.
|
||||
/// @param TargetStmt Statement where the definition is potentially being
|
||||
/// moved to (should contain a use of that definition).
|
||||
///
|
||||
/// @return { DomainDef[] -> DomainTarget[] }
|
||||
isl::map getDefToTarget(ScopStmt *DefStmt, ScopStmt *TargetStmt) {
|
||||
// No translation required if the definition is already at the target.
|
||||
if (TargetStmt == DefStmt)
|
||||
return isl::map::identity(
|
||||
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();
|
||||
simplify(Result);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Forward a load by reading from an array element that contains the same
|
||||
/// value. Typically the location it was loaded from.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user