summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Doerfert <doerfert@cs.uni-saarland.de>2016-03-24 13:50:04 +0000
committerJohannes Doerfert <doerfert@cs.uni-saarland.de>2016-03-24 13:50:04 +0000
commit733ea34f38d0c545f46e2d891a88f2677614912d (patch)
tree56d0879f7c1189f7ada5a19939f0f0fc3b779e3f
parent8ff253bfbffdaefb84d9b3edb0677ddedd6fc049 (diff)
downloadbcm5719-llvm-733ea34f38d0c545f46e2d891a88f2677614912d.tar.gz
bcm5719-llvm-733ea34f38d0c545f46e2d891a88f2677614912d.zip
[FIX] Handle accesses to "null" in MemIntrinsics
This fixes PR27035. While we now exclude MemIntrinsics from the polyhedral model if they would access "null" we could exploit this even more, e.g., remove all parameter combinations that would lead to the execution of this statement from the context. llvm-svn: 264284
-rw-r--r--polly/lib/Analysis/ScopDetection.cpp20
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp15
-rw-r--r--polly/test/ScopInfo/memset_null.ll37
3 files changed, 64 insertions, 8 deletions
diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp
index 2ceb3fa62dc..7810b94c4e5 100644
--- a/polly/lib/Analysis/ScopDetection.cpp
+++ b/polly/lib/Analysis/ScopDetection.cpp
@@ -533,17 +533,21 @@ bool ScopDetection::isValidIntrinsicInst(IntrinsicInst &II,
case llvm::Intrinsic::memmove:
case llvm::Intrinsic::memcpy:
AF = SE->getSCEVAtScope(cast<MemTransferInst>(II).getSource(), L);
- BP = dyn_cast<SCEVUnknown>(SE->getPointerBase(AF));
- // Bail if the source pointer is not valid.
- if (!isValidAccess(&II, AF, BP, Context))
- return false;
+ if (!AF->isZero()) {
+ BP = dyn_cast<SCEVUnknown>(SE->getPointerBase(AF));
+ // Bail if the source pointer is not valid.
+ if (!isValidAccess(&II, AF, BP, Context))
+ return false;
+ }
// Fall through
case llvm::Intrinsic::memset:
AF = SE->getSCEVAtScope(cast<MemIntrinsic>(II).getDest(), L);
- BP = dyn_cast<SCEVUnknown>(SE->getPointerBase(AF));
- // Bail if the destination pointer is not valid.
- if (!isValidAccess(&II, AF, BP, Context))
- return false;
+ if (!AF->isZero()) {
+ BP = dyn_cast<SCEVUnknown>(SE->getPointerBase(AF));
+ // Bail if the destination pointer is not valid.
+ if (!isValidAccess(&II, AF, BP, Context))
+ return false;
+ }
// Bail if the length is not affine.
if (!isAffine(SE->getSCEVAtScope(cast<MemIntrinsic>(II).getLength(), L), L,
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index af56aac719b..471a6669f7a 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -3942,8 +3942,17 @@ bool ScopInfo::buildAccessMemIntrinsic(
auto *DestPtrVal = MemIntr->getDest();
assert(DestPtrVal);
+
auto *DestAccFunc = SE->getSCEVAtScope(DestPtrVal, L);
assert(DestAccFunc);
+ // Ignore accesses to "NULL".
+ // TODO: We could use this to optimize the region further, e.g., intersect
+ // the context with
+ // isl_set_complement(isl_set_params(getDomain()))
+ // as we know it would be undefined to execute this instruction anyway.
+ if (DestAccFunc->isZero())
+ return true;
+
auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(SE->getPointerBase(DestAccFunc));
assert(DestPtrSCEV);
DestAccFunc = SE->getMinusSCEV(DestAccFunc, DestPtrSCEV);
@@ -3957,8 +3966,14 @@ bool ScopInfo::buildAccessMemIntrinsic(
auto *SrcPtrVal = MemTrans->getSource();
assert(SrcPtrVal);
+
auto *SrcAccFunc = SE->getSCEVAtScope(SrcPtrVal, L);
assert(SrcAccFunc);
+ // Ignore accesses to "NULL".
+ // TODO: See above TODO
+ if (SrcAccFunc->isZero())
+ return true;
+
auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(SE->getPointerBase(SrcAccFunc));
assert(SrcPtrSCEV);
SrcAccFunc = SE->getMinusSCEV(SrcAccFunc, SrcPtrSCEV);
diff --git a/polly/test/ScopInfo/memset_null.ll b/polly/test/ScopInfo/memset_null.ll
new file mode 100644
index 00000000000..b0d0be0d3b8
--- /dev/null
+++ b/polly/test/ScopInfo/memset_null.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-allow-modref-calls -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-allow-modref-calls -S -polly-codegen < %s
+;
+; Verify we can handle a memset to "null" and that we do not model it.
+; TODO: FIXME: We could use the undefined memset to optimize the code further,
+; see the TODOs in the ScopInfo.cpp.
+;
+; CHECK: Statements {
+; CHECK-NEXT: Stmt_for_cond5_preheader_us221
+; CHECK-NEXT: Domain :=
+; CHECK-NEXT: { Stmt_for_cond5_preheader_us221[0] };
+; CHECK-NEXT: Schedule :=
+; CHECK-NEXT: { Stmt_for_cond5_preheader_us221[i0] -> [0] };
+; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT: { Stmt_for_cond5_preheader_us221[i0] -> MemRef_A[0] };
+; CHECK-NEXT: }
+
+;
+target datalayout = "e-m:e-i64:64-i128:128-n8:16:32:64-S128"
+
+define void @test(i32* %A) {
+entry:
+ br i1 undef, label %for.end68, label %for.cond5.preheader.lr.ph
+
+for.cond5.preheader.lr.ph: ; preds = %entry
+ br label %for.cond5.preheader.us221
+
+for.cond5.preheader.us221: ; preds = %for.cond5.preheader.us221, %for.cond5.preheader.lr.ph
+ store i32 0, i32* %A
+ call void @llvm.memset.p0i8.i64(i8* null, i8 0, i64 undef, i32 1, i1 false)
+ br i1 true, label %for.end68, label %for.cond5.preheader.us221
+
+for.end68: ; preds = %for.cond5.preheader.us221, %entry
+ ret void
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1)
OpenPOWER on IntegriCloud