diff options
-rw-r--r-- | polly/include/polly/Support/SCEVValidator.h | 9 | ||||
-rw-r--r-- | polly/lib/Analysis/ScopDetection.cpp | 7 | ||||
-rw-r--r-- | polly/lib/Analysis/ScopInfo.cpp | 11 | ||||
-rw-r--r-- | polly/lib/Support/SCEVValidator.cpp | 14 | ||||
-rw-r--r-- | polly/test/ScopInfo/condtion-after-error-block.ll | 68 |
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 +} |