Simplify domain generation

We now add loop carried information during the second traversal of the
  region instead of in a intermediate step in-between. This makes the
  generation simpler, removes code and should even be faster.

llvm-svn: 248125
This commit is contained in:
Johannes Doerfert 2015-09-20 16:15:32 +00:00
parent 0c1123a831
commit f2cc86edae
4 changed files with 68 additions and 121 deletions

View File

@ -1015,13 +1015,11 @@ private:
/// @brief Initialize this ScopInfo .
void init(LoopInfo &LI, ScopDetection &SD, AliasAnalysis &AA);
/// @brief Add loop carried constraints to the header blocks of loops.
/// @brief Add loop carried constraints to the header block of the loop @p L.
///
/// @param L The loop to process.
/// @param LI The LoopInfo analysis.
/// @param SD The ScopDetection analysis to identify non-affine sub-regions.
/// @param DT The dominator tree of the current function.
void addLoopBoundsToHeaderDomains(LoopInfo &LI, ScopDetection &SD,
DominatorTree &DT);
void addLoopBoundsToHeaderDomain(Loop *L, LoopInfo &LI);
/// @brief Compute the branching constraints for each basic block in @p R.
///

View File

@ -1,4 +1,4 @@
//===--------- ScopInfo.cpp - Create Scops from LLVM IR ------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -850,10 +850,10 @@ static std::pair<__isl_give isl_set *, __isl_give isl_set *>
partitionSetParts(__isl_take isl_set *S, unsigned Dim) {
for (unsigned u = 0, e = isl_set_n_dim(S); u < e; u++)
S = isl_set_lower_bound_si(S, isl_dim_set, u, u == Dim ? -1 : 0);
S = isl_set_lower_bound_si(S, isl_dim_set, u, 0);
unsigned NumDimsS = isl_set_n_dim(S);
isl_set *OnlyDimS = S;
isl_set *OnlyDimS = isl_set_copy(S);
// Remove dimensions that are greater than Dim as they are not interesting.
assert(NumDimsS >= Dim + 1);
@ -881,7 +881,7 @@ partitionSetParts(__isl_take isl_set *S, unsigned Dim) {
// Remove the artificial upper bound parameters again.
BoundedParts = isl_set_remove_dims(BoundedParts, isl_dim_param, 0, Dim);
isl_set *UnboundedParts = isl_set_complement(isl_set_copy(BoundedParts));
isl_set *UnboundedParts = isl_set_subtract(S, isl_set_copy(BoundedParts));
return std::make_pair(UnboundedParts, BoundedParts);
}
@ -1560,6 +1560,7 @@ static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) {
static inline __isl_give isl_set *addDomainDimId(__isl_take isl_set *Domain,
unsigned Dim, Loop *L) {
Domain = isl_set_lower_bound_si(Domain, isl_dim_set, Dim, -1);
isl_id *DimId =
isl_id_alloc(isl_set_get_ctx(Domain), nullptr, static_cast<void *>(L));
return isl_set_set_dim_id(Domain, isl_dim_set, Dim, DimId);
@ -1595,7 +1596,6 @@ void Scop::buildDomains(Region *R, LoopInfo &LI, ScopDetection &SD,
return;
buildDomainsWithBranchConstraints(R, LI, SD, DT);
addLoopBoundsToHeaderDomains(LI, SD, DT);
propagateDomainConstraints(R, LI, SD, DT);
}
@ -1832,6 +1832,9 @@ void Scop::propagateDomainConstraints(Region *R, LoopInfo &LI,
// Under the union of all predecessor conditions we can reach this block.
Domain = isl_set_coalesce(isl_set_intersect(Domain, PredDom));
if (BBLoop && BBLoop->getHeader() == BB)
addLoopBoundsToHeaderDomain(BBLoop, LI);
// Add assumptions for error blocks.
if (containsErrorBlock(RN)) {
IsOptimized = true;
@ -1861,125 +1864,71 @@ createNextIterationMap(__isl_take isl_space *SetSpace, unsigned Dim) {
return NextIterationMap;
}
/// @brief Add @p L & all children to @p Loops if they are not in @p BoxedLoops.
static inline void
addLoopAndSubloops(Loop *L, SmallVectorImpl<Loop *> &Loops,
const ScopDetection::BoxedLoopsSetTy &BoxedLoops) {
if (BoxedLoops.count(L))
return;
void Scop::addLoopBoundsToHeaderDomain(Loop *L, LoopInfo &LI) {
int LoopDepth = getRelativeLoopDepth(L);
assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
Loops.push_back(L);
for (Loop *Subloop : *L)
addLoopAndSubloops(Subloop, Loops, BoxedLoops);
}
BasicBlock *HeaderBB = L->getHeader();
assert(DomainMap.count(HeaderBB));
isl_set *&HeaderBBDom = DomainMap[HeaderBB];
/// @brief Add loops in @p R to @p RegionLoops if they are not in @p BoxedLoops.
static inline void
collectLoopsInRegion(Region &R, LoopInfo &LI,
SmallVector<Loop *, 8> &RegionLoops,
const ScopDetection::BoxedLoopsSetTy &BoxedLoops) {
isl_map *NextIterationMap =
createNextIterationMap(isl_set_get_space(HeaderBBDom), LoopDepth);
SmallVector<Loop *, 8> Loops(LI.begin(), LI.end());
while (!Loops.empty()) {
Loop *L = Loops.pop_back_val();
isl_set *UnionBackedgeCondition =
isl_set_empty(isl_set_get_space(HeaderBBDom));
if (R.contains(L))
addLoopAndSubloops(L, RegionLoops, BoxedLoops);
else if (L->contains(R.getEntry()))
Loops.append(L->begin(), L->end());
}
}
SmallVector<llvm::BasicBlock *, 4> LatchBlocks;
L->getLoopLatches(LatchBlocks);
/// @brief Create a set from @p Space with @p Dim fixed to 0.
static __isl_give isl_set *
createFirstIterationDomain(__isl_take isl_space *Space, unsigned Dim) {
auto *Domain = isl_set_universe(Space);
Domain = isl_set_fix_si(Domain, isl_dim_set, Dim, 0);
return Domain;
}
for (BasicBlock *LatchBB : LatchBlocks) {
assert(DomainMap.count(LatchBB));
isl_set *LatchBBDom = DomainMap[LatchBB];
isl_set *BackedgeCondition = nullptr;
void Scop::addLoopBoundsToHeaderDomains(LoopInfo &LI, ScopDetection &SD,
DominatorTree &DT) {
// We iterate over all loops in the SCoP, create the condition set under which
// we will take the back edge, and then apply these restrictions to the
// header.
BranchInst *BI = cast<BranchInst>(LatchBB->getTerminator());
if (BI->isUnconditional())
BackedgeCondition = isl_set_copy(LatchBBDom);
else {
SmallVector<isl_set *, 2> ConditionSets;
int idx = BI->getSuccessor(0) != HeaderBB;
buildConditionSets(*this, BI, L, LatchBBDom, ConditionSets);
Region &R = getRegion();
SmallVector<Loop *, 8> RegionLoops;
collectLoopsInRegion(R, LI, RegionLoops, *SD.getBoxedLoops(&R));
// Free the non back edge condition set as we do not need it.
isl_set_free(ConditionSets[1 - idx]);
while (!RegionLoops.empty()) {
Loop *L = RegionLoops.pop_back_val();
int LoopDepth = getRelativeLoopDepth(L);
assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
BasicBlock *HeaderBB = L->getHeader();
isl_set *&HeaderBBDom = DomainMap[HeaderBB];
isl_set *FirstIteration =
createFirstIterationDomain(isl_set_get_space(HeaderBBDom), LoopDepth);
isl_map *NextIterationMap =
createNextIterationMap(isl_set_get_space(HeaderBBDom), LoopDepth);
isl_set *UnionBackedgeCondition =
isl_set_empty(isl_set_get_space(HeaderBBDom));
SmallVector<llvm::BasicBlock *, 4> LatchBlocks;
L->getLoopLatches(LatchBlocks);
for (BasicBlock *LatchBB : LatchBlocks) {
assert(DomainMap.count(LatchBB));
isl_set *LatchBBDom = DomainMap[LatchBB];
isl_set *BackedgeCondition = nullptr;
BranchInst *BI = cast<BranchInst>(LatchBB->getTerminator());
if (BI->isUnconditional())
BackedgeCondition = isl_set_copy(LatchBBDom);
else {
SmallVector<isl_set *, 2> ConditionSets;
int idx = BI->getSuccessor(0) != HeaderBB;
buildConditionSets(*this, BI, L, LatchBBDom, ConditionSets);
// Free the non back edge condition set as we do not need it.
isl_set_free(ConditionSets[1 - idx]);
BackedgeCondition = ConditionSets[idx];
}
int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB));
assert(LatchLoopDepth >= LoopDepth);
BackedgeCondition =
isl_set_project_out(BackedgeCondition, isl_dim_set, LoopDepth + 1,
LatchLoopDepth - LoopDepth);
UnionBackedgeCondition =
isl_set_union(UnionBackedgeCondition, BackedgeCondition);
BackedgeCondition = ConditionSets[idx];
}
isl_map *ForwardMap = isl_map_lex_le(isl_set_get_space(HeaderBBDom));
for (int i = 0; i < LoopDepth; i++)
ForwardMap = isl_map_equate(ForwardMap, isl_dim_in, i, isl_dim_out, i);
isl_set *UnionBackedgeConditionComplement =
isl_set_complement(UnionBackedgeCondition);
UnionBackedgeConditionComplement = isl_set_lower_bound_si(
UnionBackedgeConditionComplement, isl_dim_set, LoopDepth, 0);
UnionBackedgeConditionComplement =
isl_set_apply(UnionBackedgeConditionComplement, ForwardMap);
HeaderBBDom =
isl_set_subtract(HeaderBBDom, UnionBackedgeConditionComplement);
auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
// If a loop has an unbounded back edge condition part (here Parts.first)
// we do not want to assume the header will even be executed for the first
// iteration of an execution that will lead to an infinite loop. While it
// would not be wrong to do so, it does not seem helpful.
// TODO: Use the unbounded part to build runtime assumptions.
FirstIteration = isl_set_subtract(FirstIteration, Parts.first);
HeaderBBDom = isl_set_apply(Parts.second, NextIterationMap);
HeaderBBDom = isl_set_coalesce(isl_set_union(HeaderBBDom, FirstIteration));
int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB));
assert(LatchLoopDepth >= LoopDepth);
BackedgeCondition =
isl_set_project_out(BackedgeCondition, isl_dim_set, LoopDepth + 1,
LatchLoopDepth - LoopDepth);
UnionBackedgeCondition =
isl_set_union(UnionBackedgeCondition, BackedgeCondition);
}
isl_map *ForwardMap = isl_map_lex_le(isl_set_get_space(HeaderBBDom));
for (int i = 0; i < LoopDepth; i++)
ForwardMap = isl_map_equate(ForwardMap, isl_dim_in, i, isl_dim_out, i);
isl_set *UnionBackedgeConditionComplement =
isl_set_complement(UnionBackedgeCondition);
UnionBackedgeConditionComplement = isl_set_lower_bound_si(
UnionBackedgeConditionComplement, isl_dim_set, LoopDepth, 0);
UnionBackedgeConditionComplement =
isl_set_apply(UnionBackedgeConditionComplement, ForwardMap);
HeaderBBDom = isl_set_subtract(HeaderBBDom, UnionBackedgeConditionComplement);
HeaderBBDom = isl_set_apply(HeaderBBDom, NextIterationMap);
auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
HeaderBBDom = Parts.second;
isl_set *UnboundedCtx = isl_set_params(Parts.first);
isl_set *BoundedCtx = isl_set_complement(UnboundedCtx);
// TODO: Use the unbounded part to build runtime assumptions.
isl_set_free(BoundedCtx);
}
void Scop::buildAliasChecks(AliasAnalysis &AA) {

View File

@ -22,13 +22,13 @@ entry:
br label %for.cond
; CHECK-LABEL: polly.merge_new_and_old:
; CHECK: %x.addr.0.merge = phi i32 [ %x.addr.0.final_reload, %polly.merge20 ], [ %x.addr.0, %for.cond ]
; CHECK: %x.addr.0.merge = phi i32 [ %x.addr.0.final_reload, %polly.merge ], [ %x.addr.0, %for.cond ]
; CHECK: ret i32 %x.addr.0.merge
; CHECK-LABEL: polly.start:
; CHECK-NEXT: store i32 %x, i32* %x.addr.0.phiops
; CHECK-LABEL: polly.merge20:
; CHECK-LABEL: polly.merge:
; CHECK: %x.addr.0.final_reload = load i32, i32* %x.addr.0.s2a
for.cond: ; preds = %for.inc4, %entry

View File

@ -1,7 +1,7 @@
; RUN: opt %loadPolly -polly-scops -polly-detect-unprofitable -analyze < %s | FileCheck %s
;
; CHECK: Domain :=
; CHECK: [N, P, Q] -> { Stmt_if_end[i0] : (i0 >= 0 and i0 <= 1 + Q and i0 <= -1 + P and i0 <= -1 + N) or (P <= -1 and i0 >= 1 + P - Q and i0 >= 0 and i0 <= 1 + Q and i0 <= -1 + N); Stmt_if_end[0] : (N >= 1 and P <= -2 and Q <= -2) or (N >= 1 and P >= 1 and Q <= -2) or (P = -1 and N >= 1) }
; CHECK: [N, P, Q] -> { Stmt_if_end[i0] : (i0 >= 0 and i0 <= 1 + Q and i0 <= -1 + P and i0 <= -1 + N) or (P <= -1 and i0 >= 2 + P and i0 >= 0 and i0 <= 1 + Q and i0 <= -1 + N); Stmt_if_end[0] : (N >= 1 and P <= -2 and Q <= -2) or (N >= 1 and P >= 1 and Q <= -2) or (P = -1 and N >= 1) }
;
; void f(int *A, int N, int P, int Q) {
; for (int i = 0; i < N; i++) {