[polly] r247310 - Runtime error check elimination
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 10:51:28 PDT 2015
Author: jdoerfert
Date: Thu Sep 10 12:51:27 2015
New Revision: 247310
URL: http://llvm.org/viewvc/llvm-project?rev=247310&view=rev
Log:
Runtime error check elimination
Hoist runtime checks in the loop nest if they guard an "error" like event.
Such events are recognized as blocks with an unreachable terminator or a call
to the ubsan function that deals with out of bound accesses. Other "error"
events can be added easily.
We will ignore these blocks when we detect/model/optmize and code generate SCoPs
but we will make sure that they would not have been executed using the assumption
framework.
Added:
polly/trunk/test/ScopInfo/BoundChecks/two-loops.ll
Modified:
polly/trunk/include/polly/Support/ScopHelper.h
polly/trunk/lib/Analysis/ScopDetection.cpp
polly/trunk/lib/Analysis/ScopInfo.cpp
polly/trunk/lib/Support/ScopHelper.cpp
polly/trunk/test/ScopInfo/BoundChecks/single-loop.ll
Modified: polly/trunk/include/polly/Support/ScopHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ScopHelper.h?rev=247310&r1=247309&r2=247310&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ScopHelper.h (original)
+++ polly/trunk/include/polly/Support/ScopHelper.h Thu Sep 10 12:51:27 2015
@@ -99,5 +99,19 @@ llvm::Value *expandCodeFor(Scop &S, llvm
const llvm::DataLayout &DL, const char *Name,
const llvm::SCEV *E, llvm::Type *Ty,
llvm::Instruction *IP);
+
+/// @brief Check if the block is a error block.
+///
+/// A error block is currently any block that fullfills at least one of
+/// the following conditions:
+///
+/// - It is terminated by an unreachable instruction
+/// - It contains a call to a function named:
+/// + __ubsan_handle_out_of_bounds
+///
+/// @param BB The block to check.
+///
+/// @return True if the block is a error block, false otherwise.
+bool isErrorBlock(llvm::BasicBlock &BB);
}
#endif
Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=247310&r1=247309&r2=247310&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Thu Sep 10 12:51:27 2015
@@ -896,14 +896,17 @@ bool ScopDetection::allBlocksValid(Detec
return false;
}
- for (BasicBlock *BB : CurRegion.blocks())
+ for (BasicBlock *BB : CurRegion.blocks()) {
+ // Do not check exception blocks as we will never include them in the SCoP.
+ if (isErrorBlock(*BB))
+ continue;
+
if (!isValidCFG(*BB, Context) && !KeepGoing)
return false;
-
- for (BasicBlock *BB : CurRegion.blocks())
for (BasicBlock::iterator I = BB->begin(), E = --BB->end(); I != E; ++I)
if (!isValidInstruction(*I, Context) && !KeepGoing)
return false;
+ }
if (!hasAffineMemoryAccesses(Context))
return false;
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=247310&r1=247309&r2=247310&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Thu Sep 10 12:51:27 2015
@@ -1554,6 +1554,15 @@ void Scop::buildDomainsWithBranchConstra
}
BasicBlock *BB = getRegionNodeBasicBlock(RN);
+ TerminatorInst *TI = BB->getTerminator();
+
+ // Unreachable instructions do not have successors so we can skip them.
+ if (isa<UnreachableInst>(TI)) {
+ // Assume unreachables only in error blocks.
+ assert(isErrorBlock(*BB));
+ continue;
+ }
+
isl_set *Domain = DomainMap[BB];
DEBUG(dbgs() << "\tVisit: " << BB->getName() << " : " << Domain << "\n");
assert(Domain && "Due to reverse post order traversal of the region all "
@@ -1569,7 +1578,7 @@ void Scop::buildDomainsWithBranchConstra
// exit node, hence the single entry node domain is the condition set. For
// basic blocks we use the helper function buildConditionSets.
SmallVector<isl_set *, 2> ConditionSets;
- BranchInst *BI = cast<BranchInst>(BB->getTerminator());
+ BranchInst *BI = cast<BranchInst>(TI);
if (RN->isSubRegion())
ConditionSets.push_back(isl_set_copy(Domain));
else
@@ -1738,6 +1747,13 @@ void Scop::propagateDomainConstraints(Re
// Under the union of all predecessor conditions we can reach this block.
Domain = isl_set_intersect(Domain, PredDom);
+
+ // Add assumptions for error blocks.
+ if (isErrorBlock(*BB)) {
+ IsOptimized = true;
+ isl_set *DomPar = isl_set_params(isl_set_copy(Domain));
+ addAssumption(isl_set_complement(DomPar));
+ }
}
}
@@ -2435,7 +2451,7 @@ bool Scop::restrictDomains(__isl_take is
ScalarEvolution *Scop::getSE() const { return SE; }
bool Scop::isTrivialBB(BasicBlock *BB, TempScop &tempScop) {
- if (tempScop.getAccessFunctions(BB))
+ if (tempScop.getAccessFunctions(BB) && !isErrorBlock(*BB))
return false;
return true;
Modified: polly/trunk/lib/Support/ScopHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ScopHelper.cpp?rev=247310&r1=247309&r2=247310&view=diff
==============================================================================
--- polly/trunk/lib/Support/ScopHelper.cpp (original)
+++ polly/trunk/lib/Support/ScopHelper.cpp Thu Sep 10 12:51:27 2015
@@ -331,3 +331,17 @@ Value *polly::expandCodeFor(Scop &S, Sca
ScopExpander Expander(S.getRegion(), SE, DL, Name);
return Expander.expandCodeFor(E, Ty, IP);
}
+
+bool polly::isErrorBlock(BasicBlock &BB) {
+
+ for (Instruction &Inst : BB)
+ if (CallInst *CI = dyn_cast<CallInst>(&Inst))
+ if (Function *F = CI->getCalledFunction())
+ if (F->getName().equals("__ubsan_handle_out_of_bounds"))
+ return true;
+
+ if (isa<UnreachableInst>(BB.getTerminator()))
+ return true;
+
+ return false;
+}
Modified: polly/trunk/test/ScopInfo/BoundChecks/single-loop.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/BoundChecks/single-loop.ll?rev=247310&r1=247309&r2=247310&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/BoundChecks/single-loop.ll (original)
+++ polly/trunk/test/ScopInfo/BoundChecks/single-loop.ll Thu Sep 10 12:51:27 2015
@@ -1,5 +1,5 @@
-; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
-; XFAIL: *
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
;
; void exception() __attribute__((noreturn));
;
@@ -18,7 +18,18 @@
; We should detect this kernel as a SCoP and derive run-time conditions such
; that the bound-checked blocks are not part of the optimized SCoP.
-; CHECK: Assumed Context
+; CHECK: Assumed Context:
+; CHECK: [n] -> { : n <= 100 }
+
+; AST: if (n <= 100)
+; AST: for (int c0 = 0; c0 <= min(99, n - 1); c0 += 1)
+; AST: Stmt_if_end_4(c0);
+;
+; AST-NOT: for
+; AST-NOT: Stmt
+;
+; AST: else
+; AST: { /* original code */ }
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
Added: polly/trunk/test/ScopInfo/BoundChecks/two-loops.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/BoundChecks/two-loops.ll?rev=247310&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/BoundChecks/two-loops.ll (added)
+++ polly/trunk/test/ScopInfo/BoundChecks/two-loops.ll Thu Sep 10 12:51:27 2015
@@ -0,0 +1,98 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void exception() __attribute__((noreturn));
+;
+; void foo(long n, float A[100]) {
+; for (long j = 0; j < n; j++) {
+; for (long i = j; i < n; i++) {
+; if (i < 0)
+; exception();
+;
+; if (i >= 100)
+; exception();
+;
+; A[i] += i;
+; }
+; }
+; }
+;
+; CHECK: Assumed Context:
+; CHECK: [n] -> { : n <= 100 }
+
+; AST: if (n <= 100)
+; AST: for (int c0 = 0; c0 <= min(99, n - 1); c0 += 1)
+; AST: for (int c1 = 0; c1 <= min(n - c0 - 1, -c0 + 99); c1 += 1)
+; AST: Stmt_if_end_7(c0, c1);
+;
+; AST-NOT: for
+; AST-NOT: Stmt
+;
+; AST: else
+; AST: { /* original code */ }
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo(i64 %n, float* %A) #0 {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc.8, %entry
+ %j.0 = phi i64 [ 0, %entry ], [ %inc9, %for.inc.8 ]
+ %cmp = icmp slt i64 %j.0, %n
+ br i1 %cmp, label %for.body, label %for.end.10
+
+for.body: ; preds = %for.cond
+ br label %for.cond.1
+
+for.cond.1: ; preds = %for.inc, %for.body
+ %i.0 = phi i64 [ %j.0, %for.body ], [ %inc, %for.inc ]
+ %cmp2 = icmp slt i64 %i.0, %n
+ br i1 %cmp2, label %for.body.3, label %for.end
+
+for.body.3: ; preds = %for.cond.1
+ br i1 false, label %if.then, label %if.end
+
+if.then: ; preds = %for.body.3
+ call void (...) @exception() #2
+ unreachable
+
+if.end: ; preds = %for.body.3
+ %cmp5 = icmp sgt i64 %i.0, 99
+ br i1 %cmp5, label %if.then.6, label %if.end.7
+
+if.then.6: ; preds = %if.end
+ call void (...) @exception() #2
+ unreachable
+
+if.end.7: ; preds = %if.end
+ %conv = sitofp i64 %i.0 to float
+ %arrayidx = getelementptr inbounds float, float* %A, i64 %i.0
+ %tmp = load float, float* %arrayidx, align 4
+ %add = fadd float %tmp, %conv
+ store float %add, float* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %if.end.7
+ %inc = add nuw nsw i64 %i.0, 1
+ br label %for.cond.1
+
+for.end: ; preds = %for.cond.1
+ br label %for.inc.8
+
+for.inc.8: ; preds = %for.end
+ %inc9 = add nuw nsw i64 %j.0, 1
+ br label %for.cond
+
+for.end.10: ; preds = %for.cond
+ ret void
+}
+
+declare void @exception(...) #1
+
+attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noreturn "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { noreturn nounwind }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.8.0 (trunk 246853)"}
More information about the llvm-commits
mailing list