summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polly/include/polly/ScopInfo.h6
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp25
-rw-r--r--polly/test/Isl/Ast/runtime_context_with_error_blocks.ll65
-rw-r--r--polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll7
4 files changed, 93 insertions, 10 deletions
diff --git a/polly/include/polly/ScopInfo.h b/polly/include/polly/ScopInfo.h
index e18906754d0..c694355496d 100644
--- a/polly/include/polly/ScopInfo.h
+++ b/polly/include/polly/ScopInfo.h
@@ -1033,6 +1033,9 @@ private:
/// @brief True if the underlying region has a single exiting block.
bool HasSingleExitEdge;
+ /// @brief Flag to remember if the SCoP contained an error block or not.
+ bool HasErrorBlock;
+
/// Max loop depth.
unsigned MaxLoopDepth;
@@ -1517,6 +1520,9 @@ public:
/// @brief Align the parameters in the statement to the scop context
void realignParams();
+ /// @brief Return true if the SCoP contained at least one error block.
+ bool hasErrorBlock() const { return HasErrorBlock; }
+
/// @brief Return true if the underlying region has a single exiting block.
bool hasSingleExitEdge() const { return HasSingleExitEdge; }
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 319d0722dad..385ee44f97c 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -1663,8 +1663,18 @@ void Scop::realignParams() {
static __isl_give isl_set *
simplifyAssumptionContext(__isl_take isl_set *AssumptionContext,
const Scop &S) {
- isl_set *DomainParameters = isl_union_set_params(S.getDomains());
- AssumptionContext = isl_set_gist_params(AssumptionContext, DomainParameters);
+ // If we modelt all blocks in the SCoP that have side effects we can simplify
+ // the context with the constraints that are needed for anything to be
+ // executed at all. However, if we have error blocks in the SCoP we already
+ // assumed some parameter combinations cannot occure and removed them from the
+ // domains, thus we cannot use the remaining domain to simplify the
+ // assumptions.
+ if (!S.hasErrorBlock()) {
+ isl_set *DomainParameters = isl_union_set_params(S.getDomains());
+ AssumptionContext =
+ isl_set_gist_params(AssumptionContext, DomainParameters);
+ }
+
AssumptionContext = isl_set_gist_params(AssumptionContext, S.getContext());
return AssumptionContext;
}
@@ -1918,8 +1928,10 @@ void Scop::buildDomainsWithBranchConstraints(Region *R) {
// the predecessors and can therefor look at the domain of a error block.
// That allows us to generate the assumptions needed for them not to be
// executed at runtime.
- if (containsErrorBlock(RN, getRegion(), LI, DT))
+ if (containsErrorBlock(RN, getRegion(), LI, DT)) {
+ HasErrorBlock = true;
continue;
+ }
BasicBlock *BB = getRegionNodeBasicBlock(RN);
TerminatorInst *TI = BB->getTerminator();
@@ -2443,9 +2455,10 @@ Scop::Scop(Region &R, AccFuncMapType &AccFuncMap, ScopDetection &SD,
isl_ctx *Context, unsigned MaxLoopDepth)
: LI(LI), DT(DT), SE(&ScalarEvolution), SD(SD), R(R),
AccFuncMap(AccFuncMap), IsOptimized(false),
- HasSingleExitEdge(R.getExitingBlock()), MaxLoopDepth(MaxLoopDepth),
- IslCtx(Context), Context(nullptr), Affinator(this),
- AssumedContext(nullptr), BoundaryContext(nullptr), Schedule(nullptr) {}
+ HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false),
+ MaxLoopDepth(MaxLoopDepth), IslCtx(Context), Context(nullptr),
+ Affinator(this), AssumedContext(nullptr), BoundaryContext(nullptr),
+ Schedule(nullptr) {}
void Scop::init(AliasAnalysis &AA) {
buildContext();
diff --git a/polly/test/Isl/Ast/runtime_context_with_error_blocks.ll b/polly/test/Isl/Ast/runtime_context_with_error_blocks.ll
new file mode 100644
index 00000000000..86cf5834cf1
--- /dev/null
+++ b/polly/test/Isl/Ast/runtime_context_with_error_blocks.ll
@@ -0,0 +1,65 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze < %s | FileCheck %s
+;
+; Verify we do not simplify the runtime check to "true" due to the domain
+; constraints as the test contains an error block that influenced the domains
+; already.
+;
+; CHECK: if (this <= -1 || this >= 1)
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%"class.std::ctype" = type <{ %"class.std::locale::facet.base", [4 x i8], %struct.__locale_struct*, i8, [7 x i8], i32*, i32*, i16*, i8, [256 x i8], [256 x i8], i8, [6 x i8] }>
+%"class.std::locale::facet.base" = type <{ i32 (...)**, i32 }>
+%struct.__locale_struct = type { [13 x %struct.__locale_data*], i16*, i32*, i32*, [13 x i8*] }
+%struct.__locale_data = type opaque
+
+$_ZNKSt5ctypeIcE5widenEc = comdat any
+
+; Function Attrs: uwtable
+define weak_odr signext i8 @_ZNKSt5ctypeIcE5widenEc(%"class.std::ctype"* %this, i8 signext %__c) #0 comdat align 2 {
+entry:
+ br label %entry.split
+
+entry.split: ; preds = %entry
+ %_M_widen_ok = getelementptr inbounds %"class.std::ctype", %"class.std::ctype"* %this, i64 0, i32 8
+ %0 = load i8, i8* %_M_widen_ok, align 8, !tbaa !1
+ %tobool = icmp eq i8 %0, 0
+ br i1 %tobool, label %if.end, label %if.then
+
+if.then: ; preds = %entry.split
+ %idxprom = zext i8 %__c to i64
+ %arrayidx = getelementptr inbounds %"class.std::ctype", %"class.std::ctype"* %this, i64 0, i32 9, i64 %idxprom
+ %1 = load i8, i8* %arrayidx, align 1, !tbaa !7
+ br label %return
+
+if.end: ; preds = %entry.split
+ tail call void @_ZNKSt5ctypeIcE13_M_widen_initEv(%"class.std::ctype"* %this)
+ %2 = bitcast %"class.std::ctype"* %this to i8 (%"class.std::ctype"*, i8)***
+ %vtable = load i8 (%"class.std::ctype"*, i8)**, i8 (%"class.std::ctype"*, i8)*** %2, align 8, !tbaa !8
+ %vfn = getelementptr inbounds i8 (%"class.std::ctype"*, i8)*, i8 (%"class.std::ctype"*, i8)** %vtable, i64 6
+ %3 = load i8 (%"class.std::ctype"*, i8)*, i8 (%"class.std::ctype"*, i8)** %vfn, align 8
+ %call = tail call signext i8 %3(%"class.std::ctype"* %this, i8 signext %__c)
+ br label %return
+
+return: ; preds = %if.end, %if.then
+ %retval.0 = phi i8 [ %1, %if.then ], [ %call, %if.end ]
+ ret i8 %retval.0
+}
+
+declare void @_ZNKSt5ctypeIcE13_M_widen_initEv(%"class.std::ctype"*) #1
+
+attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 97e5436f69f1bfa7f3e7fd2ecd80cdee0ae95bef)"}
+!1 = !{!2, !4, i64 56}
+!2 = !{!"_ZTSSt5ctypeIcE", !3, i64 16, !6, i64 24, !3, i64 32, !3, i64 40, !3, i64 48, !4, i64 56, !4, i64 57, !4, i64 313, !4, i64 569}
+!3 = !{!"any pointer", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+!6 = !{!"bool", !4, i64 0}
+!7 = !{!4, !4, i64 0}
+!8 = !{!9, !9, i64 0}
+!9 = !{!"vtable pointer", !5, i64 0}
diff --git a/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll b/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll
index 54152f3cfec..eccff618a10 100644
--- a/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll
+++ b/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll
@@ -31,13 +31,12 @@
; timer_stop();
; }
;
-; The assumed context is empty because all statements are executed only
-; if timeit != 0. This is due to the fact that they are not "reached"
-; by the error blocks that are executed for timeit == 0.
+; The assumed context should not be empty even though all statements are
+; executed only if timeit != 0.
;
; CHECK: Region: %entry.split---%if.end.20
; CHECK: Assumed Context:
-; CHECK-NEXT: [timeit, N] -> { : }
+; CHECK-NEXT: [timeit, N] -> { : timeit = 0 }
; CHECK: Statements {
; CHECK-NOT: Stmt_if_then_split
; CHECK: Stmt_for_body
OpenPOWER on IntegriCloud