summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polly/include/polly/Support/SCEVValidator.h9
-rw-r--r--polly/lib/Analysis/ScopDetection.cpp7
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp11
-rw-r--r--polly/lib/Support/SCEVValidator.cpp14
-rw-r--r--polly/test/ScopInfo/condtion-after-error-block.ll68
5 files changed, 108 insertions, 1 deletions
diff --git a/polly/include/polly/Support/SCEVValidator.h b/polly/include/polly/Support/SCEVValidator.h
index dfa079a55d4..c8a62935051 100644
--- a/polly/include/polly/Support/SCEVValidator.h
+++ b/polly/include/polly/Support/SCEVValidator.h
@@ -105,6 +105,15 @@ const llvm::SCEV *tryForwardThroughPHI(const llvm::SCEV *Expr, llvm::Region &R,
llvm::ScalarEvolution &SE,
llvm::LoopInfo &LI,
const llvm::DominatorTree &DT);
+
+/// Return a unique non-error block incoming value for @p PHI if available.
+///
+/// @param R The region to run our code on.
+/// @param LI The loopinfo tree
+/// @param DT The dominator tree
+llvm::Value *getUniqueNonErrorValue(llvm::PHINode *PHI, llvm::Region *R,
+ llvm::LoopInfo &LI,
+ const llvm::DominatorTree &DT);
} // namespace polly
#endif
diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp
index fb951c5055e..df3acd15e06 100644
--- a/polly/lib/Analysis/ScopDetection.cpp
+++ b/polly/lib/Analysis/ScopDetection.cpp
@@ -588,6 +588,13 @@ bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
}
}
+ if (auto PHI = dyn_cast<PHINode>(Condition)) {
+ auto *Unique = dyn_cast_or_null<ConstantInt>(
+ getUniqueNonErrorValue(PHI, &Context.CurRegion, LI, DT));
+ if (Unique && (Unique->isZero() || Unique->isOne()))
+ return true;
+ }
+
// Non constant conditions of branches need to be ICmpInst.
if (!isa<ICmpInst>(Condition)) {
if (!IsLoopBranch && AllowNonAffineSubRegions &&
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 912f5e0b040..dbf38042382 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -1541,7 +1541,16 @@ bool buildConditionSets(Scop &S, BasicBlock *BB, Value *Condition,
DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
isl_set *ConsequenceCondSet = nullptr;
- if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
+
+ if (auto *PHI = dyn_cast<PHINode>(Condition)) {
+ auto *Unique = dyn_cast<ConstantInt>(
+ getUniqueNonErrorValue(PHI, &S.getRegion(), *S.getLI(), *S.getDT()));
+
+ if (Unique->isZero())
+ ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
+ else
+ ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
+ } else if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
if (CCond->isZero())
ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
else
diff --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp
index 53e400cedfc..a95eec9b64e 100644
--- a/polly/lib/Support/SCEVValidator.cpp
+++ b/polly/lib/Support/SCEVValidator.cpp
@@ -762,4 +762,18 @@ const SCEV *tryForwardThroughPHI(const SCEV *Expr, Region &R,
return Expr;
}
+Value *getUniqueNonErrorValue(PHINode *PHI, Region *R, LoopInfo &LI,
+ const DominatorTree &DT) {
+ Value *V = nullptr;
+ for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
+ BasicBlock *BB = PHI->getIncomingBlock(i);
+ if (!isErrorBlock(*BB, *R, LI, DT)) {
+ if (V)
+ return nullptr;
+ V = PHI->getIncomingValue(i);
+ }
+ }
+
+ return V;
+}
} // namespace polly
diff --git a/polly/test/ScopInfo/condtion-after-error-block.ll b/polly/test/ScopInfo/condtion-after-error-block.ll
new file mode 100644
index 00000000000..5fa3c1ee469
--- /dev/null
+++ b/polly/test/ScopInfo/condtion-after-error-block.ll
@@ -0,0 +1,68 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+; Verify that we allow scops containing uniform branch conditions, where all
+; but one incoming block comes from an error condition.
+
+; CHECK: Statements {
+; CHECK-NEXT: Stmt_A
+; CHECK-NEXT: Domain :=
+; CHECK-NEXT: [p] -> { Stmt_A[] };
+; CHECK-NEXT: Schedule :=
+; CHECK-NEXT: [p] -> { Stmt_A[] -> [1, 0] };
+; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT: [p] -> { Stmt_A[] -> MemRef_X[0] };
+; CHECK-NEXT: Stmt_loop
+; CHECK-NEXT: Domain :=
+; CHECK-NEXT: [p] -> { Stmt_loop[i0] : p >= 13 and 0 <= i0 <= 1025 };
+; CHECK-NEXT: Schedule :=
+; CHECK-NEXT: [p] -> { Stmt_loop[i0] -> [0, i0] };
+; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT: [p] -> { Stmt_loop[i0] -> MemRef_X[0] };
+; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
+; CHECK-NEXT: [p] -> { Stmt_loop[i0] -> MemRef_phi__phi[] };
+; CHECK-NEXT: }
+
+declare void @bar()
+
+define void @foo(float* %X, i64 %p) {
+entry:
+ br label %br
+
+br:
+ %cmp1 = icmp sle i64 %p, 12
+ br i1 %cmp1, label %A, label %br2
+
+br2:
+ %cmp3 = icmp sle i64 %p, 12
+ br i1 %cmp3, label %cond, label %loop
+
+loop:
+ %indvar = phi i64 [0, %br2], [%indvar.next, %loop]
+ %indvar.next = add nsw i64 %indvar, 1
+ store float 41.0, float* %X
+ %cmp2 = icmp sle i64 %indvar, 1024
+ br i1 %cmp2, label %loop, label %merge
+
+cond:
+ br label %cond2
+
+cond2:
+ call void @bar()
+ br label %merge
+
+merge:
+ %phi = phi i1 [false, %cond2], [true, %loop]
+ br i1 %phi, label %A, label %B
+
+A:
+ store float 42.0, float* %X
+ br label %exit
+
+B:
+ call void @bar()
+ store float 41.0, float* %X
+ br label %exit
+
+exit:
+ ret void
+}
OpenPOWER on IntegriCloud