Allow loops with multiple back edges

In order to allow multiple back edges we:
    - compute the conditions under which each back edge is taken
    - build the union over all these conditions, thus the condition that
      any back edge is taken
    - apply the same logic to the union we applied to a single back edge

llvm-svn: 248120
This commit is contained in:
Johannes Doerfert 2015-09-20 15:00:20 +00:00
parent 7175bdfbe4
commit 06c57b594c
3 changed files with 88 additions and 37 deletions

View File

@ -699,10 +699,6 @@ bool ScopDetection::isValidInstruction(Instruction &Inst,
bool ScopDetection::canUseISLTripCount(Loop *L,
DetectionContext &Context) const {
// Ensure the loop has a single back edge.
if (L->getNumBackEdges() != 1)
return false;
// Ensure the loop has valid exiting blocks, otherwise we need to
// overapproximate it as a boxed loop.
SmallVector<BasicBlock *, 4> ExitingBlocks;

View File

@ -1913,28 +1913,7 @@ void Scop::addLoopBoundsToHeaderDomains(LoopInfo &LI, ScopDetection &SD,
int LoopDepth = getRelativeLoopDepth(L);
assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
BasicBlock *LatchBB = L->getLoopLatch();
assert(LatchBB && "TODO implement multiple exit loop handling");
isl_set *LatchBBDom = DomainMap[LatchBB];
isl_set *BackedgeCondition = nullptr;
BasicBlock *HeaderBB = L->getHeader();
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];
}
isl_set *&HeaderBBDom = DomainMap[HeaderBB];
isl_set *FirstIteration =
createFirstIterationDomain(isl_set_get_space(HeaderBBDom), LoopDepth);
@ -1942,23 +1921,52 @@ void Scop::addLoopBoundsToHeaderDomains(LoopInfo &LI, ScopDetection &SD,
isl_map *NextIterationMap =
createNextIterationMap(isl_set_get_space(HeaderBBDom), LoopDepth);
int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB));
assert(LatchLoopDepth >= LoopDepth);
BackedgeCondition =
isl_set_project_out(BackedgeCondition, isl_dim_set, LoopDepth + 1,
LatchLoopDepth - 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);
}
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 *BackedgeConditionComplement =
isl_set_complement(BackedgeCondition);
BackedgeConditionComplement = isl_set_lower_bound_si(
BackedgeConditionComplement, isl_dim_set, LoopDepth, 0);
BackedgeConditionComplement =
isl_set_apply(BackedgeConditionComplement, ForwardMap);
HeaderBBDom = isl_set_subtract(HeaderBBDom, BackedgeConditionComplement);
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);

View File

@ -0,0 +1,47 @@
; RUN: opt %loadPolly -analyze -polly-scops -polly-detect-unprofitable < %s | FileCheck %s
;
; CHECK: Domain :=
; CHECK: [N, P] -> { Stmt_if_end[i0] : (i0 >= 1 + P and i0 >= 0 and i0 <= -1 + N) or (i0 >= 0 and i0 <= -1 + P and i0 <= -1 + N) };
;
; void f(int *A, int N, int P, int Q) {
; for (int i = 0; i < N; i++) {
; if (i == P)
; continue;
; A[i]++;
; }
; }
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @f(i32* %A, i32 %N, i32 %P, i32 %Q) {
entry:
%tmp = sext i32 %N to i64
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %if.then ], [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%cmp = icmp slt i64 %indvars.iv, %tmp
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%tmp1 = trunc i64 %indvars.iv to i32
%cmp1 = icmp eq i32 %tmp1, %P
br i1 %cmp1, label %if.then, label %if.end
if.then: ; preds = %for.body
br label %for.cond
if.end: ; preds = %for.body
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
%tmp2 = load i32, i32* %arrayidx, align 4
%inc = add nsw i32 %tmp2, 1
store i32 %inc, i32* %arrayidx, align 4
br label %for.inc
for.inc: ; preds = %if.end, %if.then
br label %for.cond
for.end: ; preds = %for.cond
ret void
}